# 3. Go语言流程控制
# 3.1 if 分支结构
Golang中,if 关键字用于条件判断,如果满足条件就做某事:
score := 80
if score > 90{
fmt.Println("成绩优秀")
}
如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行,if 和 else 后的两个代码块是相互独立的分支,只能执行其中一个:
score := 80
if score >= 60 {
fmt.Println("成绩及格")
} else {
fmt.Println("成绩不及格")
}
如果存在第三个分支或者更多分支,则可以使用下面这种的形式:
score := 80
if score >= 60 && score < 70 {
fmt.Println("成绩及格")
} else if score >= 60 && score < 80 {
fmt.Println("成绩良好")
} else if score >= 80 && score <= 100 {
fmt.Println("成绩优秀")
} else {
fmt.Println("成绩不及格")
}
else if 分支的数量是没有限制的,但是为了代码的可读性,还是不要在 if 后面加入太多的 else if 结构,如果必须使用这种形式,则尽可能把先满足的条件放在前面。
总结起来 if else 基本语法如下:
if condition {
// do something
} else if condition2 {
// do something
} else if condition3 {
//do something
} ... { 多个else if,再次忽略写法
//do something
}else {
// do something
}
还有一点,关键字 if 和 else 之后的左大括号{
必须和关键字在同一行,如果你使用了 else if 结构,则前段代码块的右大括号}
必须和 else if 关键字在同一行,这两条规则都是被编译器强制规定的。例如下面就是非法代码:
if x{
}
else { // 无效的
}
if 还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断,代码如下:
if score := 80; score > 70 {
fmt.Println("score > 70")
}else{
fmt.Println("score < 70")
}
或者也可以根据一个函数的返回信息进行判断,示例如下:
if err := Connect(); err != nil {
fmt.Println(err)
return
}
Connect 是一个带有返回值的函数,err:=Connect() 是一个语句,执行 Connect 后,将错误保存到 err 变量中。err != nil 才是 if 的判断表达式,当 err 不为空时,打印错误并返回。这种写法可以将返回值与判断放在一行进行处理,而且返回值的作用范围被限制在 if、else 语句组合中。
# 3.2 for 循环结构
Go语言中的循环语句只支持 for 关键字,而不支持 while 和 do-while 结构。
Go语言的For循环有3中形式,只有其中的一种使用分号:
for init; condition; post { }
for condition { }
for { }
init: 一般为赋值表达式,给控制变量赋初值;
condition: 关系表达式或逻辑表达式,循环控制条件;
post: 一般为赋值表达式,给控制变量增量或减量。
下面我们用例子给出这三种模式的代码:
for x := 0; x < 10; x++ { //for init; condition; post{}模式
fmt.Println(x)
}
i := 10
for i > 0 { // 替代 while (i > 0) {}, 属于 for condition {} 模式
fmt.Println(i)
i--
}
j := 0
for { //替代 while (true) {}, 属于 for {}模式
j++
if j > 10 {
break
}
}
熟悉了Go语言的基本循环格式后,我们来用for循环实现一个九九乘法表的输出:
for x := 1; x <= 9; x++ { //从1遍历到9
for y := 1; y <= x; y++ { //乘法遍历
fmt.Printf("%d*%d=%d ", x, y, x*y)
}
fmt.Println() //手动换行
}
编译输出:
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
# 3.3 switch case 结构语句
Go语言中的 switch 结构使用上比其他语言更加灵活,表达式不需要为常量,甚至不需要为整数,case 按照从上到下的顺序进行求值,直到找到匹配的项,如果 switch 没有表达式,则对 true 进行匹配,因此,可以将 if else-if else 改写成一个 switch。
Go 编程语言中 switch 语句的语法如下:
switch var1 {
case val1:
...
case val2:
...
default:
...
}
变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。 您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。
【示例】
var a = "dog"
switch a {
case "dog":
fmt.Println("wangwang")
case "duck":
fmt.Println("gaga")
default:
fmt.Println("...")
}
score := 90
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
case score >= 60:
fmt.Println("D")
default:
fmt.Println("E")
}
编译运行:
wangwang
A
在Go语言中 case 是一个独立的代码块,case执行完之后一般break,但可以使用 fallthrough 来强制执行下一个 case 代码块 代码如下:
a := 2
switch a {
case 1:
fmt.Println("a=1")
case 2:
fmt.Println("a=2")
fallthrough
case 3:
fmt.Println("a=3")
case 4:
fmt.Println("a=4")
default:
fmt.Println("default")
}
编译运行:
a=2
a=3
switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型:
var x interface{}
x = 22
switch x.(type) {
case int:
fmt.Println("int")
case int64:
fmt.Println("int64")
case float64:
fmt.Println("float64")
case bool:
fmt.Println("bool")
case string:
fmt.Println("string")
default:
fmt.Printf("%T", x)
}
编译运行:
int
# 3.4 goto break continue 语句
goto语句
goto 语句通过标签进行代码间的无条件跳转,同时 goto 语句在快速跳出循环、避免重复退出上也有一定的帮助,goto对应(标签)既可以定义在for循环前面,也可以定义在for循环后面,当跳转到标签地方时,继续执行标签下面的代码,示例:
for a := 5; a > 0; a-- {
fmt.Println(a)
if a == 3 {
goto loop
}
}
fmt.Println("run here")
loop:
fmt.Println("goto here")
编译执行:
5
4
3
goto here
break语句
break 语句可以结束 for、switch 和 select 的代码块,另外 break 语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的 for、switch 和 select 的代码块上。
for a := 0; a < 5; a++ {
for t := 0; t < 3; t++ {
if t == 2 {
break //跳出本层for循环
}
fmt.Println(a, t)
}
}
编译运行:
0 0
0 1
1 0
1 1
2 0
2 1
3 0
3 1
4 0
4 1
下面来演示下结合标签实现break跳出上一层for循环,示例:
OuterLoop:
for i := 0; i < 2; i++ {
for j := 0; j < 5; j++ {
switch j {
case 2:
fmt.Println(i, j)
break OuterLoop
case 3:
fmt.Println(i, j)
break OuterLoop
default:
fmt.Println(i, j)
}
}
}
fmt.Println("here")
编译运行:
0 0
0 1
0 2
here
continue语句
continue 语句可以结束当前本次循环,开始下一次的循环迭代过程,仅限在 for 循环内使用, 示例:
for a := 0; a < 5; a++ {
for t := 0; t < 3; t++ {
if t == 2 {
continue //跳出本次for循环
}
fmt.Println(a, t)
}
}
编译运行:
0 0
0 1
1 0
1 1
2 0
2 1
3 0
3 1
4 0
4 1
在 continue 语句后添加标签时,表示开始标签对应的循环,例如:
OuterLoop:
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
switch j {
case 2:
fmt.Println(i, j)
continue OuterLoop
}
}
}
代码输出结果如下:
0 2
1 2
2 2
最后对 goto break continue 做一个总结:
- 三个语句都可以配合标签使用
- 标签区分大小写,如果标签定义出来后,不使用将会报错
- continue 单独使用是跳出本次循环;break单独使用是跳出本层循环
- continue break配合标签使用可以用于多层循环跳出, break 配合标签主要跳出 最外层循环,而continue配合标签是跳出当次循环
- goto配合标签主要是调整到执行位置,而continue break配合标签则是跳出循