流程控制是编程语言中用来控制程逻辑的走向和执行次序的语法/机制,大致分为三种
- 1、顺序结构:从上向下,逐行执行
- 2、选择结构:满足条件,某段代码才会执行1次,总共0-1次,例如分支语句:if,switch,select
- 3、循环结构:满足条件,某段代码会被重复的执行多次,总共0-N次,例如循环语句:for
Go语言中最常用的流程控制有if
和for
,而switch
和goto
主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。
完整语法如下
| if 表达式1 { |
| 分支1 |
| } else if 表达式2 { |
| 分支2 |
| } else{ |
| 分支3 |
| } |
| |
| |
Go语言规定
- 1、与
if
匹配的左括号{
必须与if和表达式
放在同一行,{
放在其他位置会触发编译错误。
- 2、 理由同上,与
else
匹配的{
也必须与else
写在同一行,同时else
也必须与上一个if
或else if
右边的大括号在同一行。
举例
| score := 60 |
| if score >= 90 { |
| fmt.Println("优") |
| } else if score >= 80 { |
| fmt.Println("良") |
| } else { |
| fmt.Println("差") |
| } |
if条件判断还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断,举个如下
| if score := 60;score >= 90 { |
| fmt.Println("优") |
| } else if score >= 80 { |
| fmt.Println("良") |
| } else { |
| fmt.Println("差") |
| } |
思考题: 普通写法与特殊写法的区别在哪里?
| 答案:特殊写法中声明的score只能在if判断内部使用 |
Go 语言中的所有循环类型均可以使用for
关键字来完成。
| for 初始语句;条件表达式;结束语句{ |
| 循环体 |
| } |
for循环会一直循环执行循环体代码直到条件表达式返回false
则终止循环,示例如下
| for i := 0; i < 10; i++ { |
| fmt.Println(i) |
| } |
| i := 0 |
| for ; i < 10; i++ { |
| fmt.Println(i) |
| } |
| i := 0 |
| for i < 10 { |
| fmt.Println(i) |
| i++ |
| } |
上述写法类似于其他编程语言中的while
,在while
后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环
| for true { |
| fmt.Println("ok") |
| } |
| |
| |
| for { |
| fmt.Println("ok") |
| } |
for循环可以通过break
、goto
、return
、panic
语句强制退出循环。
Go语言中可以使用for range
遍历数组、切片、字符串、map 及通道(channel)。 通过for range
遍历的返回值有以下规律:
-
数组、切片、字符串返回索引和值。
| |
| names:=[4]string{"egon","张三","李四","王五"} |
| for i,v:=range names{ |
| fmt.Println(i,v) |
| } |
| |
| 0 egon |
| 1 张三 |
| 2 李四 |
| 3 王五 |
| |
| |
| names:=[]string{"egon","张三","李四","王五"} |
| for i,v:=range names{ |
| fmt.Println(i,v) |
| } |
| |
| 0 egon |
| 1 张三 |
| 2 李四 |
| 3 王五 |
| |
| |
| for i,v:=range "hello你好"{ |
| fmt.Printf("%d %q\n",i,v) |
| } |
| |
| 0 'h' |
| 1 'e' |
| 2 'l' |
| 3 'l' |
| 4 'o' |
| 5 '你' |
| 8 '好' |
-
map返回键和值
| ages:=map[string]int{ |
| "egon":18, |
| "张三":20, |
| "李四":30, |
| } |
| for i,v:=range ages{ |
| fmt.Println(i,v) |
| } |
| |
| 李四 30 |
| egon 18 |
| 张三 20 |
-
通道(channel)只返回通道内的值。
使用switch
语句可方便地对大量的值进行条件判断,从而减少大量if条件的次数,
| day := 1 |
| switch day { |
| case 1: |
| fmt.Println("星期一") |
| case 2: |
| fmt.Println("星期二") |
| case 3: |
| fmt.Println("星期三") |
| case 4: |
| fmt.Println("星期四") |
| case 5: |
| fmt.Println("星期五") |
| case 6: |
| fmt.Println("星期六") |
| case 0: |
| fmt.Println("星期天") |
| default: |
| fmt.Println("无效的输入!") |
| } |
Go语言规定每个switch
只能有一个default
分支。
一个case分支可以有多个值,多个case值中间使用英文逗号分隔。
| day := 1 |
| switch day { |
| case 1,2,3,4,5: |
| fmt.Println("工作日") |
| case 6,0: |
| fmt.Println("休息日") |
| default: |
| fmt.Println("无效的输入!") |
| } |
分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量。例如:
| level:=9 |
| switch { |
| case level >= 20: |
| fmt.Println("荣耀王者") |
| case level >= 10: |
| fmt.Println("钻石玩家") |
| case level >= 0: |
| fmt.Println("倔强青铜") |
| default: |
| fmt.Println("无效的输入!") |
| } |
fallthrough
语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。
| level:=23 |
| switch { |
| case level >= 20: |
| fmt.Println("荣耀王者") |
| fallthrough |
| case level >= 10: |
| fmt.Println("钻石玩家") |
| case level >= 0: |
| fmt.Println("倔强青铜") |
| default: |
| fmt.Println("无效的输入!") |
| } |
| |
| |
| 荣耀王者 |
| 钻石玩家 |
goto
语句可以无条件地跳转到指定标签的位置
| for i:=1;i<=2;i++{ |
| for j:=1;j<=3;j++{ |
| fmt.Printf("%v-%v\n",i,j) |
| goto xxx |
| |
| } |
| } |
| fmt.Println("后续其他代码1") |
| fmt.Println("后续其他代码2") |
| fmt.Println("后续其他代码3") |
| |
| xxx: |
| fmt.Println("飞过来。。。") |
| |
| } |
Go语言中使用goto
语句能简化一些代码的实现过程,比如在快速跳出循环、避免重复退出上有一定的帮助。
例如:
| |
| breakTag := false |
| |
| for i := 1; i <= 2; i++ { |
| for j := 1; j <= 3; j++ { |
| fmt.Printf("%v-%v\n", i, j) |
| breakTag = true |
| break |
| } |
| |
| if breakTag { |
| break |
| } |
| } |
| fmt.Println("后续其他代码1") |
| fmt.Println("后续其他代码2") |
| fmt.Println("后续其他代码3") |
| |
| |
| for i := 1; i <= 2; i++ { |
| for j := 1; j <= 3; j++ { |
| fmt.Printf("%v-%v\n", i, j) |
| goto xxx |
| } |
| |
| } |
| |
| xxx: |
| fmt.Println("后续其他代码1") |
| fmt.Println("后续其他代码2") |
| fmt.Println("后续其他代码3") |
break
语句可用于结束for
、switch
和select
的代码块,如下
| for i:=0;i<10;i++{ |
| if i==3 { |
| break |
| } |
| fmt.Println(i) |
| |
| } |
我们还可以在break
语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for
、switch
和 select
的代码块上,如下
| var choice int |
| |
| loop1: |
| for { |
| fmt.Println("===================>外层循环重新开始啦<===================") |
| |
| loop2: |
| for { |
| fmt.Print("内层循环,输0退出外层,输1只退内存: ") |
| _, _ = fmt.Scan(&choice) |
| if choice == 0 { |
| break loop2 |
| } else if choice == 1 { |
| break loop1 |
| } |
| } |
| } |
| |
| fmt.Println("其他后续代码......") |
continue
语句仅限在for
循环内使用,用于结束当前/本次循环,直接进入下一次的循环
| for i:=0;i<5;i++{ |
| if i==3 { |
| continue |
| } |
| fmt.Println(i) |
| |
| } |
在 continue
语句后添加标签时,表示由此直接进入标签对应的循环。例如:
| var choice int |
| i:=0 |
| |
| loop1: |
| for { |
| fmt.Println("===================>外层循环重新开始啦<===================") |
| |
| loop2: |
| for { |
| fmt.Print("内层循环,输0重新进入loop2,输1重新进入loop1,输2继续: ") |
| _, _ = fmt.Scan(&choice) |
| if choice == 0 { |
| continue loop2 |
| } else if choice == 1 { |
| continue loop1 |
| } |
| fmt.Println("姑娘站在门口冲你喊:来啊来啊来啊...",i) |
| i++ |
| } |
| |
| } |
| package main |
| |
| import "fmt" |
| |
| func main() { |
| |
| users := map[string]string{ |
| "egon": "123", |
| "tom": "456", |
| } |
| |
| var inpUser string |
| var inpPwd string |
| var errNum int64 = 0 |
| |
| for { |
| if errNum == 3 { |
| fmt.Println("超过最大尝试次数") |
| break |
| } |
| fmt.Printf("请输入您的账号:") |
| fmt.Scanln(&inpUser) |
| |
| fmt.Printf("请输入您的密码:") |
| fmt.Scanln(&inpPwd) |
| |
| pwd := users[inpUser] |
| if pwd == inpPwd { |
| fmt.Println("登录成功") |
| loop2: |
| for { |
| var choice string |
| fmt.Printf(` |
| 1 起飞 |
| 2 降落 |
| 3 发射 |
| 4、注销 |
| 5、关机 |
| `) |
| fmt.Scanln(&choice) |
| |
| switch { |
| case choice == "1": |
| fmt.Println("起飞。。。") |
| case choice == "2": |
| fmt.Println("降落。。。") |
| case choice == "3": |
| fmt.Println("发射。。。") |
| case choice == "4": |
| break loop2 |
| |
| case choice == "5": |
| goto xxx |
| default: |
| fmt.Println("输入命令不存在") |
| } |
| |
| } |
| } else { |
| fmt.Println("账号或密码错误") |
| errNum++ |
| } |
| |
| } |
| |
| xxx: |
| fmt.Println("关机走人") |
| |
| } |