【GO语言】流程控制语句
一、if 语句
IF 语句书写格式
- 如果逻辑表达式成立,执行{}里的内容
- 逻辑表达式不需要加()
- “{” 必须紧跟在逻辑表达式之后,不能另起一行
- 变量赋值语句允许同时初始化多个局部变量
- 逻辑表达式中可以含有变量和常量
- if 语句中仅允许包含1个分号,在分号前初始化一些局部变量(仅在该 if 块内可见)
- else if 允许拥有 0个、1个、多个
- else 允许拥有 0个 或 1个
- else if 和 else 书写格式都必须跟在上一个语句块 “}” 之后,不允许另起一行
if 变量赋值语句 ; 逻辑表达式 { 执行代码语句块 } else if 逻辑表达式 { 执行代码语句块 } else if 逻辑表达式 { 执行代码语句块 } else { 执行代码语句块 }范例:
func main() { if a, b, c := 10, 22, 22; a > b && a > c { fmt.Println("a is max") } else if b > a && b > c { fmt.Println("b is max") } else if c > a && c > b { fmt.Println("c is max") } else { fmt.Println("I don't kown") } }输出结果:
二、switch 语句
- switch-case-default 可模拟 if-else if-else,但只能实现相等判断
- switch 和 case 后面可以跟常量、变量或函数表达式,只要它们表示的数据类型相同就行
- case后面可以跟多个值,只要有一个值满足就行
范例:
var color string = "black" func main() { switch color { case "red": fmt.Println("stopped") case "green": fmt.Println("running") default: fmt.Printf("color %s undefined", color) } }输出结果:
范例:
var color string = "black" func main() { switch color { case "red": fmt.Println("stopped") case "green": fmt.Println("running") case "white", "black": fmt.Println("faild") default: fmt.Printf("color %s undefined", color) } }输出结果:
空switch
switch后带表达式时,switch-case 只能模拟相等的情况,如果 switch 后不带表达式,case 后可以跟任意的条件表达式
范例:
func a_b(a int, b int) { switch { case a > b: fmt.Println("a is bigger") case a < b: fmt.Println("b is bigger") default: fmt.Println("a = b") } } func main() { a_b(10, 20) a_b(30, 20) a_b(20, 20) }输出结果:
switch Type
用于判断 interface{} 类型,或 interface{} 对应类型的值处理
错误范例:
// 只做类型判断时: 如果对 num 进行数据处理,由于num的类型依旧为 interface{},会禁止进行数据处理 // 可在数据处理前时进行数据格式强制转换后,处理数据 例:func switch_type_value2(){} func switch_type(num interface{}) { switch num.(type) { case int: fmt.Printf("num type is %T\n", num+1) case float64: fmt.Printf("num type is %T\n", num) case string: fmt.Printf("num type is %T\n", num) default: fmt.Println("num type is others") } } func main() { switch_type(3) }输出结果:
范例:
// 只做类型判断时: 如果对 num 进行数据处理,由于num的类型依旧为 interface{},会禁止进行数据处理 // 可在数据处理前时进行数据格式强制转换后,处理数据 例:func switch_type_value2(){} func switch_type(num interface{}) { switch num.(type) { case int: fmt.Printf("num type is %T\n", num) case float64: fmt.Printf("num type is %T\n", num) case string: fmt.Printf("num type is %T\n", num) default: fmt.Println("num type is others") } } // 进行类型判断并且需要调用interface{} 值时:会在 case type 字段将 value 进行类型转换,因此可以直接进行数据处理 // 等价于 func switch_type_value2(){} func switch_type_value(num interface{}) { switch value := num.(type) { case int: // 此处 value 已经被强制转换为 int 类型 fmt.Printf("num type is %T,\tnum+1 = %d\n", value, value+1) case float64: // 此处 value 已经被强制转换为 float64 类型 fmt.Printf("num type is %T,\tnum+3.4 = %.1f\n", value, value+3.4) case string: // 此处 value 已经被强制转换为 string 类型 fmt.Printf("num type is %T,\tnum+'abc' = %s\n", value, value+"abc") case byte, rune: // 当出现多个类型时,value 依旧保持 interface{} 类型 fmt.Printf("num type is %T\n", value) default: fmt.Printf("num type is others,num = %v\n", value) } } // 此函数等价于 func switch_type_value(){} func switch_type_value1(num interface{}) { switch num.(type) { case int: value := num.(int) fmt.Printf("num type is %T,\tnum+1 = %d\n", value, value+1) case float64: value := num.(float64) fmt.Printf("num type is %T,\tnum+2.2 = %.1f\n", value, value+2.2) case string: value := num.(string) fmt.Printf("num type is %T,\tnum+'abc' = %s\n", value, value+"abc") default: fmt.Println("num type is others") } } func main() { fmt.Println("swtich_type--------------------------") switch_type(3.1) switch_type(3) switch_type("3") fmt.Println("swtich_type_value--------------------------") switch_type_value(3.2) switch_type_value(3) switch_type_value("3") fmt.Println("swtich_type_value1--------------------------") switch_type_value1(3.2) switch_type_value1(3) switch_type_value1("3") }输出结果:
fallthrough
- 从上往下,只要找到成立的case,就不再执行后面的 case 了。所以为了提高性能,把大概率会满足的情况往前放
- case 里如果带了 fallthrough ,则执行完本 case 代码内容 不执行条件判断,强制执行下一个 case 代码内容
- 在 switch Type 语句的 case 子句中不能使用 fallthrough
范例(未使用fallthrough,语句成功匹配到 case 后续的 case default 内容直接跳过):
func user_permission(level int) { fmt.Printf("用户等级 %d, 开放以下权限:", level) switch { case level >= 100: fmt.Printf("勋章\n") case level >= 70: fmt.Printf("交易\n") case level >= 50: fmt.Printf("师徒\n") case level >= 30: fmt.Printf("排位\n") case level >= 10: fmt.Println("商城\n") case level < 10: fmt.Println("未达到10级,无任何权限\n") } } func main() { user_permission(180) user_permission(91) user_permission(70) user_permission(7) }输出结果:
范例(使用 fallthrough 导致后续 case 被强制执行):
func user_permission(level int) { fmt.Printf("用户等级 %d, 开放以下权限:", level) switch { case level >= 100: fmt.Printf("勋章 ") fallthrough case level >= 70: fmt.Printf("交易 ") fallthrough case level >= 50: fmt.Printf("师徒 ") fallthrough case level >= 30: fmt.Printf("排位 ") fallthrough case level >= 10: fmt.Println("商城") fallthrough // 由于此处执行了 fallthrough , 下一个 case level < 10 会忽略判断结果强制执行 case level < 10: fmt.Println("未达到10级,无任何权限") } } func main() { user_permission(180) user_permission(91) user_permission(70) user_permission(7) }输出结果:
范例(合理使用 fallthrough):
func user_permission(level int) { fmt.Printf("用户等级 %d, 开放以下权限:", level) switch { case level >= 100: fmt.Printf("勋章 ") fallthrough case level >= 70: fmt.Printf("交易 ") fallthrough case level >= 50: fmt.Printf("师徒 ") fallthrough case level >= 30: fmt.Printf("排位 ") fallthrough case level >= 10: fmt.Println("商城") case level < 10: fmt.Println("未达到10级,无任何权限") } } func main() { user_permission(180) user_permission(91) user_permission(70) user_permission(7) }输出结果:
三、for 循环
- FOR 语句书写格式:
- 逻辑表达式成立,执行{}中的内容,{}内容执行完毕执行后续操作
- 局部变量只作用于当前 for 语句块
- 初始化的变量可以放在 for 语句上面(此时不再仅作为当前 for 语句的局部变量)
- 后续操作可以放在 for 内部
- 只有条件判断时,前后的分号可以省略
- for {} 是一个无限循环
- 变量赋值语句、逻辑表达语句、后续操作可以同时处理多个值
for 变量赋值语句 ; 逻辑表达式; 后续操作 { 执行代码语句块 }范例:
func for_deined() { arr := [...]int{1, 7, 9, 5, 6} // 格式1 fmt.Println("formate 1 ===================") for i := 0; i < len(arr); i++ { fmt.Println(arr[i]) } // 格式2 fmt.Println("formate 2 ===================") for i := 0; i < len(arr); { fmt.Println(arr[i]) i++ } // 格式3 fmt.Println("formate 3 ===================") { i := 0 for i < len(arr) { fmt.Println(arr[i]) i++ } } } func main() { for_deined() }输出结果:
范例:
func for_deined2() { for i, sum := 1, 1; i < 10 && sum < 100; i, sum = i+1, sum*i { fmt.Printf("i = %d\t sum = %d\n", i, sum) } } func main() { for_deined2() }输出结果:
for range
- 遍历数组或切片
- 遍历string
- 遍历map,不保证遍历顺序
- 遍历channl,需要提前 close
- for range 拿到的是数据值拷贝
// 遍历数组或切片 for i,ele := range arr {} // 遍历string(汉字占用3个字节) for i,ele := range "这是一个string" {} // ele 是一个 rune // 遍历map for key,value := range m {} // 遍历channl for ele := range ch {}
四、break 和 continue 语句
- break 和 continue 用于控制 for 循环的代码流程,并且只针对所在最近的 for 循环生效(当前所在的 for 代码语句块)
- break: 退出 for 循环,且本轮 break 后面的代码不再执行
- continue: 本轮 continue 后面的代码不再执行,进入下一轮的 for 循环
五、goto 与 Label 语句
- 可以通过使用 goto label 语句更加灵活的控制语句流程
- label 定义位置没有限制,可以在 goto 调用之前定义,也可以在 goto 调用之后定义,但是已经定义的 label 必须在某个地方被调用
- goto label 跳转到 定义的 label 之后一行开始运行代码
package main import "fmt" func echo_page(page int, size int, arr []int) { start := (page - 1) * size end := page * size if len(arr) < end { end = len(arr) } for _, v := range arr[start:end] { fmt.Printf("%d\t", v) } } func main() { arr := []int{23, 42, 21, 3, 4, 5, 62, 13, 4, 2, 34, 1, 3, 14, 14, 13, 31, 41} arr_len := len(arr) page := 0 size := 5 L1: page++ echo_page(page, size, arr) fmt.Printf("\n") if arr_len > page*size { goto L1 } }
continue Label 与 break Label
continue 与 break 也可以与 Label 结合使用,可以实现跳转到更外层的 for 循环
continue 与 break 调用的 Label 必须写在语句所在 for 循环体以外,goto Label 可以针对任意位置
范例:
// 等价于 func continue_1() {} func continue_label_1() { arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} brr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} for _, a := range arr { L1: for _, b := range brr { if a == b { fmt.Printf("%d*%d=%d\n", a, b, a*b) continue L1 } fmt.Printf("%d*%d=%d\t", a, b, a*b) } } } func continue_1() { arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} brr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} for _, a := range arr { for _, b := range brr { if a == b { fmt.Printf("%d*%d=%d\n", a, b, a*b) continue } fmt.Printf("%d*%d=%d\t", a, b, a*b) } } } // 实现continue跳出上一层循环 func continue_label_2() { arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} brr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} L1: for _, a := range arr { for _, b := range brr { if a == b { fmt.Printf("%d*%d=%d\n", a, b, a*b) continue L1 // break } fmt.Printf("%d*%d=%d\t", a, b, a*b) } } } func main() { continue_label_1() fmt.Println("==========================================================") continue_label_2() }输出结果: