Go里的流程控制有以下几种:
- if - else 条件语句
- switch - case 选择语句
- for - range 循环语句
- goto 无条件跳转语句
- defer 延迟执行
if-else
基本用法
func TestIfElse(condition string) {
if condition == "1" {
fmt.Println("ONE")
} else if condition == "2" {
fmt.Println("TWO")
} else if condition == "3" {
fmt.Println("THREE")
} else {
fmt.Println("OTHER")
}
}
func Execute() {
TestIfElse("1")
}
高级写法
在 if 里可以允许先运行一个表达式,取得变量后,再对其进行判断,比如第一个例子里代码也可以写成这样
func TestIfElseHight() {
if a := GetCondition("ONE"); a == 1 {
fmt.Println("TEST")
}
}
func GetCondition(condition string) int {
if condition == "ONE" {
return 1
}
return 0
}
Go语言明确不支持三元表达式
switch-case
简单用法
拿 switch 后的表达式分别和 case 后的表达式进行对比,只要有一个 case 满足条件,就会执行对应的代码块,然后直接退出 switch - case ,如果 一个都没有满足,才会执行 default 的代码块。
func TestSwitchCase() {
condition := "CASE1"
switch condition {
case "CASE1":
fmt.Println("CASE1 PRINT")
case "CASE2":
fmt.Println("CASE2 PRINT")
default:
fmt.Println("DEFAULT PRINT")
}
}
一个case多个条件
case后接多个条件
func TestSwitchCase() {
condition := "CASE2"
switch condition {
case "CASE1", "CASE3", "CASE5":
fmt.Println("ODD PRINT")
case "CASE2", "CASE4", "CASE6":
fmt.Println("EVEN PRINT")
default:
fmt.Println("DEFAULT PRINT")
}
}
case后的常量不能重复,不然会报错
duplicate case “XXX” in switch
switch接函数
switch 后面可以接一个函数,只要保证 case 后的值类型与函数的返回值 一致即可
func GetCondition(condition string) int {
if condition == "ONE" {
return 1
}
return 0
}
func TestSwitchCaseFunc() {
switch GetCondition("ONE") {
case 1:
fmt.Print("ONE PRINT")
case 0:
fmt.Print("TWO PRINT")
default:
fmt.Print("DEFAULT")
}
}
switch可以不接表达式,不接任何东西时相当于if-elseif-else
score := 30
switch {
case score >= 95 && score <= 100:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
case score >= 60:
fmt.Println("合格")
case score >= 0:
fmt.Println("不合格")
default:
fmt.Println("输入有误...")
}
switch的穿透能力
正常情况下 switch - case 的执行顺序是:只要有一个 case 满足条件,就会直接退出 switch - case ,如果 一个都没有满足,才会执行 default 的代码块。
但是有一种情况是例外。
那就是当 case 使用关键字 fallthrough
开启穿透能力的时候。
func TestSwitchFallThrough() {
condition := "CASE1"
switch condition {
case "CASE1", "CASE3", "CASE5":
fmt.Println("ODD PRINT")
fallthrough
case "CASE2", "CASE4", "CASE6":
fmt.Println("EVEN PRINT")
default:
fmt.Println("DEFAULT PRINT")
}
}
// 输出结果为
ODD PRINT
EVEN PRINT
fallthrough
只能穿透一层
for循环
语法规则
for [condition | ( init; condition; increment ) | Range]
{
statement(s);
}
for后面可以接:
condition
[一个条件表达式]( init; condition; increment )
[最常见的]Range
range表达式- 什么都不接
样例
func TestFor() {
a := 1
for a <= 5 {
fmt.Printf("a: %v\n", a)
a++
}
for i := 1; i <= 5; i++ {
fmt.Printf("i: %v\n", i)
}
rangeArr := []string{"C1", "C2", "C3"}
for _, item := range rangeArr {
fmt.Printf("item: %v\n", item)
}
number := 0
for {
if number >= 5 {
break
}
fmt.Printf("number: %v\n", number)
number++
}
}
输出
a: 1
a: 2
a: 3
a: 4
a: 5
i: 1
i: 2
i: 3
i: 4
i: 5
item: C1
item: C2
item: C3
number: 0
number: 1
number: 2
number: 3
number: 4
go无条件跳转
语法规则
goto
后接一个标签,这个标签的意义是告诉 Go程序下一步要执行哪里的代码。
所以这个标签如何放置,放置在哪里,是 goto 里最需要注意的。
goto 标签;
...
...
标签: 表达式;
简单例子
func TestGoto() {
goto printB
fmt.Println("AAAAA")
printB:
fmt.Println("BBBBB")
}
结果是BBBBB
,不会输出A
,直接就跳过去了。
注意事项
goto语句和标签之前不能有变量申明
func TestGoto() {
goto printB
fmt.Println("AAAAA")
var testP = "CCC"
printB:
fmt.Println("BBBBB")
}
这样会报错processcontrol\processcontrol.go:10:7: goto printB jumps over declaration of testP at processcontrol\processcontrol.go:13:6
常见用法
func TestGotoNormal() {
i := 1
loopPrint:
if i <= 5 {
fmt.Printf("i: %v\n", i)
i++
goto loopPrint
}
j := 1
for {
if j >= 5 {
goto loopBreak
}
fmt.Printf("j: %v\n", j)
j++
}
loopBreak:
k := 1
loopContinue:
for k <= 5 {
if k%2 == 1 {
k++
goto loopContinue
}
fmt.Printf("k: %v\n", k)
k++
}
}
输出
i: 1
i: 2
i: 3
i: 4
i: 5
j: 1
j: 2
j: 3
j: 4
k: 2
k: 4
defer延迟语句
延迟调用
defer 的用法很简单,只要在后面跟一个函数的调用,就能实现将这个 xxx
函数的调用延迟到当前函数执行完后(return后)再执行。
func TestDefer() {
defer fmt.Println("BBBBBB")
fmt.Println("AAAAAA")
}
输出:
AAAAAA
BBBBBB
及时求值的变量快照
使用 defer 只是延时调用函数,此时传递给函数里的变量,不应该受到后续程序的影响。
如下:
func TestDefer() {
str := "BBBBB"
defer fmt.Println(str)
str = "AAAAA"
fmt.Println(str)
}
闭包
这样写会产生闭包问题,str变量在外部。
func TestDeferFunc() {
str := "AAAA"
defer func() {
fmt.Printf("str: %v\n", str)
}()
str = "BBBBB"
fmt.Printf("str: %v\n", str)
}
输结果
str: BBBBB
str: BBBBB
str这个变量,在defer打印出来之后,还是输出的BBBBB
。
换种方式:
func TestDeferFunc() {
str := "AAAA"
defer func(s string) {
fmt.Printf("s: %v\n", s)
}(str)
str = "BBBBB"
fmt.Printf("str: %v\n", str)
}
输出
str: BBBBB
s: AAAA
执行顺序问题
defer执行语句像一个栈一样,先入后出,先写后执行
func TestDeferOrder() {
defer println("AAAAA")
defer println("BBBBB")
defer println("CCCCC")
}
结果:
CCCCC
BBBBB
AAAAA