流程控制语句 if 1 2 3 if 5 > 9 { fmt.Println("5>9" ) }
如果逻辑表达式成立,就会执行{}里的内容。
逻辑表达式不需要加()。
“{“必须紧跟在逻辑表达式后面,不能另起一行。
1 2 3 if c, d, e := 5 , 9 , 2 ; c < d && (c > e || c > 3 ) { fmt.Println("fit" ) }
逻辑表达中可以含有变量或常量。
if句子中允许包含1个(仅1个)分号,在分号前初始化一些局部变量(即只在if块内可见)。
if-else的用法
1 2 3 4 5 6 7 8 9 10 color := "black" if color == "red" { fmt.Println("stop" ) } else if color == "green" { fmt.Println("go" ) } else if color == "yellow" { fmt.Println("stop" ) } else { fmt.Printf("invalid traffic signal: %s\n" , strings.ToUpper(color)) }
if表达式嵌套
1 2 3 4 5 6 7 8 9 10 if xxx { if xxx { }else if xxx{ }else { } }else { if xxx { }else { } }
注意太深的嵌套不利于代码的维护,比如
1 2 3 4 5 6 7 8 9 10 if (true ) { if (true ) { if (true ) { if (true ) { if (true ) { } } } } }
switch 1 2 3 4 5 6 7 8 9 color := "black" switch color {case "green" : fmt.Println("go" ) case "red" : fmt.Println("stop" ) default : fmt.Printf("invalid traffic signal: %s\n" , strings.ToUpper(color)) }
switch-case-default可能模拟if-else if-else,但只能实现相等判断。
switch和case后面可以跟常量、变量或函数表达式,只要它们表示的数据类型相同就行。
case后面可以跟多个值,只要有一个值满足就行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func add (a int ) int { return a + 10 } func switch_expression () { var a int = 5 switch add(a) { case 15 : fmt.Println("right" ) default : fmt.Println("wrong" ) } const B = 15 switch B { case add(a): fmt.Println("right" ) default : fmt.Println("wrong" ) } }
switch后带表达式时,switch-case只能模拟相等的情况;如果switch后不带表达式,case后就可以跟任意的条件表达式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func switch_condition () { color := "yellow" switch color { case "green" : fmt.Println("go" ) case "red" , "yellow" : fmt.Println("stop" ) } switch { case add(5 ) > 10 : fmt.Println("right" ) default : fmt.Println("wrong" ) } }
switch Type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 func switch_type () { var num interface {} = 6.5 switch num.(type ) { case int : fmt.Println("int" ) case float32 : fmt.Println("float32" ) case float64 : fmt.Println("float64" ) case byte : fmt.Println("byte" ) default : fmt.Println("neither" ) } switch value := num.(type ) { case int : fmt.Printf("number is int %d\n" , value) case float64 : fmt.Printf("number is float64 %f\n" , value) case byte , string : fmt.Printf("number is inerface %v\n" , value) default : fmt.Println("neither" ) } switch num.(type ) { case int : value := num.(int ) fmt.Printf("number is int %d\n" , value) case float64 : value := num.(float64 ) fmt.Printf("number is float64 %f\n" , value) case byte : value := num.(byte ) fmt.Printf("number is byte %d\n" , value) default : fmt.Println("neither" ) } }
fallthrough 强制执行下一个case(或default)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 func fall_throth (age int ) { fmt.Printf("您的年龄是%d, 您可以:\n" , age) switch { case age > 50 : fmt.Println("出任国家首脑" ) fallthrough case age > 25 : fmt.Println("生育子女" ) fallthrough case age > 22 : fmt.Println("结婚" ) fallthrough case age > 18 : fmt.Println("开车" ) fallthrough case age > 16 : fmt.Println("参加工作" ) case age > 15 : fmt.Println("上高中" ) fallthrough case age > 3 : fmt.Println("上幼儿园" ) } }
for 1 2 3 4 arr := []int {1 , 2 , 3 , 4 , 5 } for i := 0 ; i < len (arr); i++ { fmt.Printf("%d: %d\n" , i, arr[i]) }
for 初始化局部变量;条件表达式;后续操作
1 for sum, i := 0 , 0 ; i < len (arr) && sum < 100 ; sum, i = sum*1 , i+1
局部变量指仅在for块内可见。
初始化变量可以放在for上面。
后续操作可以放在for块内部。
只有条件判断时,前后的分号可以不要。
for{}是一个无限循环。
for range
遍历数组或切片
遍历string
for i, ele := range “我会唱ABC” //ele是rune类型
遍历map,go不保证遍历的顺序
for key, value := range m
遍历channel,遍历前一定要先close
for ele := range ch
for range拿到的是数据的拷贝
for嵌套 矩阵乘法需要用到三层for循环嵌套。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 func nest_for () { const SIZE = 4 A := [SIZE][SIZE]float64 {} for i := 0 ; i < SIZE; i++ { for j := 0 ; j < SIZE; j++ { A[i][j] = rand.Float64() } } B := [SIZE][SIZE]float64 {} for i := 0 ; i < SIZE; i++ { for j := 0 ; j < SIZE; j++ { B[i][j] = rand.Float64() } } rect := [SIZE][SIZE]float64 {} for i := 0 ; i < SIZE; i++ { for j := 0 ; j < SIZE; j++ { prod := 0.0 for k := 0 ; k < SIZE; k++ { prod += A[i][k] * B[k][j] } rect[i][j] = prod } } i, j := 2 , 1 fmt.Println(A[i]) for _, row := range B { fmt.Printf("%g " , row[j]) } fmt.Println() fmt.Println(rect[i][j]) }
break与continue
break与continue用于控制for循环的代码流程,并且只针对最靠近自己的外层for循环。
break:退出for循环,且本轮break下面的代码不再执行。
continue:本轮continue下面的代码不再执行,进入for循环的下一轮。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func complex_break_continue () { const SIZE = 5 arr := [SIZE][SIZE]int {} for i := 0 ; i < SIZE; i++ { fmt.Printf("开始检查第%d行\n" , i) if i%2 == 1 { for j := 0 ; j < SIZE; j++ { fmt.Printf("开始检查第%d列\n" , j) if arr[i][j]%2 == 0 { continue } fmt.Printf("将要检查第%d列\n" , j+1 ) } break } } }
goto与Label 1 2 3 4 5 var i int = 4 MY_LABEL: i += 3 fmt.Println(i) goto MY_LABEL
1 2 3 4 5 6 7 8 9 if i%2 == 0 { goto L1 } else { goto L2 } L1: i += 3 L2: i *= 3
goto与Label结合可以实现break的功能,甚至比break更强大。
1 2 3 4 5 6 7 8 for i := 0 ; i < SIZE; i++ {L2: for j := 0 ; j < SIZE; j++ { goto L1 } } L1: xxx
break、continue与Label结合使用可以跳转到更外层的for循环。
continue和break针对的Label必须写在for前面,而goto可以针对任意位置的Label。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 func break_label () { const SIZE = 5 arr := [SIZE][SIZE]int {} L1: for i := 0 ; i < SIZE; i++ { L2: fmt.Printf("开始检查第%d行\n" , i) if i%2 == 1 { L3: for j := 0 ; j < SIZE; j++ { fmt.Printf("开始检查第%d列\n" , j) if arr[i][j]%3 == 0 { break L1 } else if arr[i][j]%3 == 1 { goto L2 } else { break L3 } } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var num int L1: for i := 0 ; i < 10 ; { fmt.Println("开始" ) fmt.Printf("i=%d\n" , i) L2: fmt.Println("开始2" ) i += 1 fmt.Printf("i=%d\n" , i) fmt.Print("请输入:" ) fmt.Scan(&num) switch num { case 1 : break L1 case 2 : continue L1 case 3 : goto L2 case 4 : goto L1 } } fmt.Println("结束" )