条件判断结构:if else
分支选择结构:switch case
循环结构:for
break:退出for或switch结构(以及select)
continue:进入下一次for迭代
虽然Go是类C的语言,但Go在这些流程控制语句中的条件表达式部分不使用括号。甚至有些时候使用括号会报错,但有些复杂的条件判断需要使用括号改变优先级。
如:
if (name == "longshuai" && age > 23) || (name == "xiaofang" && age < 22) {
print("yeyeye!!!")
}
if语句
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
注意,Go对语法要求很严格。左大括号{
必须和if、else或else if在同一行,右大括号}
必须换行,如果有else或else if,则必须紧跟这两个关键字。也就是说,上面的代码结构中,大括号的使用位置是强制规范的,不能随意换行放置。
在Go中,if语句的condition前面可以加上初始化语句,例如Go中很常见的:
if val := 10; val > max {
// do something
}
它在一定程度上等价于:
val := 10
if val > max {
// do something
}
但注意,前面简写的方式中,val
的作用域只在if范围内,if外面无法访问这个val。如果在if语句之前已经定义了一个val,那么这个val将被if中的val掩盖,直到if退出后才恢复。
func main() {
val := 20
if val := 10; val > 3 {
println("true")
}
println(val) // 输出20
}
一种解决方式是if中的初始化语句不要使用:=
,而是直接使用=
,但这样会修改原始的值。
func main() {
val := 20
if val = 10; val > 3 {
println("true")
}
println(val) // 输出10
}
在Go中,经常使用两个(或多个)返回值的函数,一个返回值作为值,另一个作为布尔类型的判断值,或者作为错误信息。通常会使用if语句去检测多个返回值的函数是否成功。
但注意,一般有两种判断返回值:一种是ok类型,一种是err类型的错误信息。前者是布尔值,后者是表明错误信息的字符串,如果没错误,则err为nil。
value,ok := func_name()
if !ok {
// func_name执行错误
os.Exit(1)
}
value,err := func_name()
if err != nil {
// func_name执行错误
os.Exit(1)
// 或 return err
}
将上面的简写一下,得到更常见的判断方式:
if value,ok := func_name();ok {
// ok为true,函数执行成功
} else {
// ok为false,函数执行失败
os.Exit(1)
}
if value,err := func_name();err != nil {
// err不为nil,说明出现错误
return err
//或os.Exit(1)
} else {
// err为空,说明执行正确
}
switch语句
switch语句用于提供分支测试。有两种swithc结构:expression switch和type switch,本文暂时只介绍expression switch,它用于判断表达式是否为true。
对于expression switch,也有三种形式:等值比较、表达式比较、初始化表达式。
等值比较结构:当var1的值为val1时,执行statement1,当var1的值为val2时,执行statement2,都不满足时,执行默认的语句statement。
switch var1 {
case val1:
statement1
case val2:
statement2
default:
statement
}
等值比较局限性很大,只能将var1和case中的值比较是否相等。如果想比较不等,或者其它表达式类型,可以使用下面的表达式比较结构。
表达式比较结构:评估每个case结构中的condition,只要评估为真就执行,然后退出(默认情况下)。
switch {
case condition1:
statement1
case condition2:
statement2
default:
statement
}
初始化表达式:可以和if一样为switch加上初始化表达式,同样作用域只在switch可见。但注意,initialization后面记得加上分号";"结尾。见下文示例。
switch initialization; { // 不要省略分号
case condition1:
statement1
case condition2:
statement2
defautl:
statement
}
default
是可选的,且可以写在switch的任何位置。
如果case中有多个要执行的语句,可以加大括号,也可以不加大括号。当只有一个语句的时候,statement可以和case在同一行。
case中可以提供多个用于测试的值,使用逗号分隔,只要有一个符合,就满足条件:
switch var1 {
case val1,val2,val3:
statement1
case val4,val5:
statement2
default:
statement
}
例如:
val := 20
switch val {
case 10, 11, 15:
println(11, 15)
case 16, 20, 22: // 命中
println(16, 20, 22)
default:
println("nothing")
}
即使是表达式比较结构,也一样可以使用逗号分隔多个表达式,这时和使用逻辑或"||"是等价的:
func main() {
val := 21
switch {
case val % 4 == 0:
println(0)
case val % 4 == 1, val % 4 == 2: //命中
println(1, 2)
default:
println("3")
}
}
默认情况下case命中就结束,所以所有的case中只有一个会被执行。但如果想要执行多个,可以在执行完的某个case的最后一个语句上加上fallthrough
,它会无条件地直接跳转到下一条case并执行,如果下一条case中还有fallthrough,则相同的逻辑。此外,fallthrough的后面必须只能是下一个case或default,不能是额外的任何语句,否则会报错。
例如:
func main() {
val := 21
switch val % 4 {
case 0:
println(0)
case 1, 2: // 命中
println(1, 2) // 输出
fallthrough // 执行下一