Go语言的循环与条件判断
Go语言是一种编译型的静态语言,它提供了丰富的流程控制结构,可以用来实现各种复杂的逻辑。本文将介绍Go语言中最常用的两种流程控制结构:循环和条件判断。
循环
循环是一种重复执行一段代码的方式,直到满足某个条件或者达到某个目标。Go语言中只有一种循环结构,就是for
循环。for
循环的基本语法如下:
for init; condition; post {
// 循环体
}
其中,init
是一个可选的赋值表达式,用于初始化循环变量;condition
是一个布尔表达式,用于判断是否继续循环;post
是一个可选的赋值表达式,用于更新循环变量。每次循环都会先执行init
(只在第一次执行),然后检查condition
,如果为真,则执行循环体,再执行post
,然后重复这个过程,直到condition
为假,就退出循环。
例如,下面的代码用for
循环计算1到10的数字之和:
sum := 0
for i := 1; i <= 10; i++ {
sum += i
}
fmt.Println(sum) // 输出55
Go语言中的for
循环非常灵活,可以根据需要省略某些部分。例如,如果省略了init
和post
部分,就相当于一个while
循环:
sum := 1
for sum <= 10 {
sum += sum
}
fmt.Println(sum) // 输出16
如果连condition
也省略了,就相当于一个无限循环:
for {
// do something
}
要想跳出无限循环,可以使用break
语句。要想跳过当前循环,可以使用continue
语句。
另外,Go语言还提供了一种特殊的for
循环,叫做范围遍历(range loop)。它可以对字符串、数组、切片、映射等可迭代的对象进行遍历,并返回每个元素的索引和值。它的语法如下:
for key, value := range collection {
// do something with key and value
}
其中,key
和value
是可以省略或者替换为其他变量名的。如果只想获取索引或者值,可以使用空白标识符(下划线)来忽略另一个。例如:
// 遍历字符串中的字符
for i, c := range "Hello" {
fmt.Println(i, c) // 输出0 72, 1 101, 2 108, 3 108, 4 111
}
// 遍历数组中的元素
numbers := [6]int{1, 2, 3, 5}
for _, x := range numbers {
fmt.Println(x) // 输出1, 2, 3, 5, 0, 0
}
// 遍历映射中的键值对
map1 := make(map[int]float32)
map1[1] = 1.0
map1[2] = 2.0
map1[3] = 3.0
map1[4] = 4.0
for key := range map1 {
fmt.Println(key) // 输出1, 2, 3, 4(顺序不一定)
}
条件判断
条件判断是一种根据不同的条件执行不同的代码的方式。Go语言中提供了以下几种条件判断语句:
if
语句:用于测试一个布尔表达式是否为真,如果为真,则执行if
后面的代码块,否则忽略该代码块。if...else
语句:在if
语句的基础上,可以添加一个可选的else
语句,用于在布尔表达式为假时执行另一个代码块。if...else if...else
语句:在if...else
语句的基础上,可以添加一个或多个else if
语句,用于在多个条件之间进行选择。switch
语句:用于根据一个表达式的值或者一个类型的值进行多分支的选择,并执行相应的代码块。select
语句:用于在多个通道(channel)操作之间进行选择,并执行相应的代码块。
if语句
if
语句的基本语法如下:
if condition {
// 条件为真时执行
}
其中,condition
是一个布尔表达式,可以是一个变量、常量、函数调用或者复杂的逻辑运算。如果condition
的值为真(true),则执行大括号中的代码块,否则跳过该代码块。例如:
x := 10
if x > 0 {
fmt.Println("x is positive") // 输出x is positive
}
Go语言中的if
语句还有一个特点,就是可以在条件判断之前执行一个简单的赋值语句,该语句声明的变量作用域只能在该if
语句块内。例如:
if x := 10; x > 0 {
fmt.Println("x is positive") // 输出x is positive
}
fmt.Println(x) // 编译错误,x未定义
if…else语句
有时候,我们需要在条件不满足时执行另一段代码,这时候就可以使用if...else
语句。它的基本语法如下:
if condition {
// 条件为真时执行
} else {
// 条件为假时执行
}
其中,如果condition
为真,则执行第一个代码块,否则执行第二个代码块。例如:
x := -10
if x > 0 {
fmt.Println("x is positive")
} else {
fmt.Println("x is negative or zero") // 输出x is negative or zero
}
if…else if…else语句
有时候,我们需要在多个条件之间进行选择,这时候就可以使用if...else if...else
语句。它的基本语法如下:
if condition1 {
// 条件1为真时执行
} else if condition2 {
// 条件2为真时执行
} else {
// 其他情况执行
}
其中,如果condition1
为真,则执行第一个代码块;如果condition2
为真,则执行第二个代码块;如果都不为真,则执行最后一个代码块。例如:
score := 85
if score >= 90 {
fmt.Println("A")
} else if score >= 80 {
fmt.Println("B") // 输出B
} else if score >= 60 {
fmt.Println("C")
} else {
fmt.Println("D")
}
switch语句
当我们需要在多个可能的值之间进行选择时,可以使用switch
语句。它的基本语法如下:
switch expression {
case value1:
// 当expression等于value1时执行
case value2, value3:
// 当expression等于value2或者value3时执行
default:
// 其他情况执行
}
其中,expression
是一个表达式,可以是一个变量、常量、函数调用或者复杂的运算。case
后面跟着一个或多个可能的值,用逗号分隔。如果expression
的值和某个case
后面的值相等,则执行该case
对应的代码块,并跳出switch
语句;如果都不相等,则执行default
对应的代码块。例如:
x := 2
switch x {
case 1:
fmt.Println("x is 1")
case 2, 3:
fmt.Println("x is 2 or 3") // 输出x is 2 or 3
default:
fmt.Println("x is not 1, 2 or 3")
}
Go语言中的switch
语句还有一些特点,如下:
expression
可以省略,相当于默认为true
,这时候每个case
后面跟着一个布尔表达式,相当于多个if...else if...else
语句。- 每个代码块不需要使用
break
语句来跳出,执行完毕后自动跳出。如果需要继续执行下一个代码块,可以使用fallthrough
语句。 - 可以在条件判断之前执行一个简单的赋值语句,该语句声明的变量作用域只能在该
switch
语句块内。
例如:
// 省略expression
n := 5
switch {
case n > 0 && n < 10:
fmt.Println("n is between 0 and 10") // 输出n is between 0 and 10
case n > 10 && n < 20:
fmt.Println("n is between 10 and 20")
default:
fmt.Println("n is out of range")
}
// 使用fallthrough
s := "Hello"
switch s {
case "Hello":
fmt.Println("Hello")
fallthrough // 继续执行下一个代码块
case "World":
fmt.Println("World") // 输出World
default:
fmt.Println("Default")
}
// 使用赋值语句
switch x := 10; x {
case 10:
fmt.Println("x is 10") // 输出x is 10
default:
fmt.Println("x is not 10")
}
fmt.Println(x) // 编译错误,x未定义
select语句
当我们需要在多个通道(channel)操作之间进行选择时,可以使用select
语句。它的基本语法如下:
select {
case <-ch1:
// 当ch1可读时执行
case ch2 <- x:
// 当ch2可写时执行
default:
// 其他情况执行
}
其中,每个case
后面跟着一个通道的读或写操作,如果该操作可以进行,则执行该case
对应的代码块,并跳出select
语句;如果都不可以进行,则执行default
对应的代码块。如果没有提供default
代码块,则会阻塞等待某个通道操作可行。
例如:
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(time.Second)
ch1 <- 100
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- 200
}()
select {
case x := <-ch1:
fmt.Println("Received", x, "from ch1") // 输出Received 100 from ch1
case y := <-ch2:
fmt.Println("Received", y, "from ch2")
default:
fmt.Println("No data received") // 不会输出这一行,因为会等待某个通道可读
}