🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 流程控制 Go语言中最常用的流程控制有`if`和`for`,而`switch`和`goto`主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。 ## if else(分支结构) `if`条件判断的格式如下: ~~~ if 表达式1 { 分支1 } else if 表达式2 { 分支2 } else{ 分支3 } ~~~ eg1: ~~~ func ifDemo1() { score := 65 if score >= 90 { fmt.Println("A") } else if score > 75 { fmt.Println("B") } else { fmt.Println("C") } } ~~~ ### if条件判断特殊写法 if条件判断还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断 eg2: ~~~ func ifDemo2() { if score := 65; score >= 90 { fmt.Println("A") } else if score > 75 { fmt.Println("B") } else { fmt.Println("C") } } ~~~ 还可以进行`if ... else` 的嵌套 ## for(循环结构) 所有循环类型均可以使用`for`关键字来完成。 for循环的基本格式如下: ~~~ for 初始语句;条件表达式;结束语句{ 循环体语句 } ~~~ 条件表达式返回`true`时循环体不停地进行循环,直到条件表达式返回`false`时自动退出循环。 ~~~ func Demo() { for i := 0; i < 10; i++ { fmt.Println(i) } } ~~~ for循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如: ~~~go func Demo2() { i := 0 for ; i < 10; i++ { fmt.Println(i) } } ~~~ for循环的初始语句和结束语句都可以省略,例如: ~~~ func Demo3() { i := 0 for i < 10 { fmt.Println(i) i++ } } ~~~ 这种写法类似于其他编程语言中的`while`,在`while`后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环。 ### 无限循环 ~~~ for { 循环体语句 } ~~~ for循环可以通过`break`、`goto`、`return`、`panic`语句强制退出循环。 ## for range(键值循环) Go语言中可以使用`for range`遍历数组、切片、字符串、map 及通道(channel)。 通过`for range`遍历的返回值有以下规律: 1. 数组、切片、字符串返回索引和值。 2. map返回键和值。 3. 通道(channel)只返回通道内的值。 ## switch case 使用`switch`语句可方便地对大量的值进行条件判断。 ~~~ func switchDemo() { finger := 3 switch finger { case 1: fmt.Println("大拇指") case 2: fmt.Println("食指") case 3: fmt.Println("中指") case 4: fmt.Println("无名指") case 5: fmt.Println("小拇指") default: fmt.Println("无效的输入!") } } ~~~ Go语言规定每个`switch`只能有一个`default`分支。 一个分支可以有多个值,多个case值中间使用英文逗号分隔。 ~~~ func testSwitch3() { switch n := 7; n { case 1, 3, 5, 7, 9: fmt.Println("奇数") case 2, 4, 6, 8: fmt.Println("偶数") default: fmt.Println(n) } } ~~~ 分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量。例如: ~~~ func switchDemo4() { age := 30 switch { case age < 25: fmt.Println("好好学习吧") case age > 25 && age < 35: fmt.Println("好好工作吧") case age > 60: fmt.Println("好好享受吧") default: fmt.Println("活着真好") } } ~~~ `fallthrough`语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。 ~~~go func switchDemo5() { s := "a" switch { case s == "a": fmt.Println("a") fallthrough case s == "b": fmt.Println("b") case s == "c": fmt.Println("c") default: fmt.Println("...") } } 输出:a b ~~~ ## goto(跳转到指定标签) `goto`语句通过标签进行代码间的无条件跳转。`goto`语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用`goto`语句能简化一些代码的实现过程 ~~~ func gotoDemo2() { for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { // 设置退出标签 goto breakTag } fmt.Printf("%v-%v\n", i, j) } } return // 标签 breakTag: fmt.Println("结束for循环") } ~~~ ## break(跳出循环) `break`语句可以结束`for`、`switch`和`select`的代码块。 `break`语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的`for`、`switch`和`select`的代码块上。 eg: ~~~ func breakDemo1() { BREAKDEMO1: for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { break BREAKDEMO1 } fmt.Printf("%v-%v\n", i, j) } } fmt.Println("...") } ~~~ `注:break + 代码块名称 ` 是一个退出循环的小技巧 ## continue(继续下次循环) `continue`语句可以结束当前循环,开始下一次的循环迭代过程,仅限在`for`循环内使用。 在`continue`语句后添加标签时,表示开始标签对应的循环。 eg: ~~~ func continueDemo() { forloop1: for i := 0; i < 5; i++ { // forloop2: for j := 0; j < 5; j++ { if i == 2 && j == 2 { continue forloop1 } fmt.Printf("%v-%v\n", i, j) } } } ~~~ `continue + 代码块标签 `和 `break + 代码块名称` 有异曲之处 ##select select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。 ~~~ select{ case 条件  :       TODO you want case 条件  :        TODO you want /* 你可以定义任意数量的 case */ default:/* 可选 */         TODO you want } ~~~ select 语句的语法: * 每个 case 都必须是一个通信 * 所有 channel 表达式都会被求值 * 所有被发送的表达式都会被求值 * 如果任意某个通信可以进行,它就执行,其他被忽略。 * 如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。 否则: 1. 如果有 default 子句,则执行该语句。 2. 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。 ~~~ packagemain import"fmt" func main(){ var c1, c2, c3 chan int var i1, i2 int select{ case i1=<-c1:          fmt.Printf("received ",i1," from c1 \n") case c2 <-i2:          fmt.Printf("sent ",i2," to c2 \n") case i3,ok:=(<-c3):// same as: i3, ok := <-c3 if ok{         fmt.Printf("received ",i3," from c3 \n") } else {          fmt.Printf("c3 is closed \n") } default:          fmt.Printf("no communication \n") } } ~~~