<Go>2 程序流程控制
本文最后更新于:2023年6月27日 上午
2 程序流程控制
2.1 运算符
运算符是一种特殊的符号,用以表示数据运算、赋值、比较等
主要有 6 类:
- 算术运算符:++、--、+、-、*、/
- 赋值运算符:=、+=、-=、&=、|=、^=、!=
- 比较运算符 / 关系运算符:>、<、<=、>=、==、!=
- 逻辑运算符:&&、||
- 位运算符:>>、<<、>>>、&、^、!、|
- 其他运算符:取址符
&
、指针符*
特别地:Go 中的 ++
、--
都只能独立使用,且只能出现在变量后侧:
var i int = 10
i++
/* --i */ // 错误用法
/* var n int = i++ */ // 错误用法
另外,Go 语言明确不支持三元运算符
2.2 键盘输入、屏幕输出
这两个功能包含在 fmt 包中。
导入 fmt 包:
import "fmt"
#屏幕输出:
-
fmt.Print(a... interface{})
:输出该语句fmt.Println(a... interface{})
:输出该语句,之后换行fmt.Printf(format string, a... interface{})
:格式化输出语句
#键盘输入:
-
fmt.Scanln(a... interface{})
:获取输入,保存到传入参数中。直到换行时才停止扫描fmt.Scanf(format string, a... interface{})
:根据指定格式,将成功读取的空白分割的值保存到传入参数中
2.3 程序流程控制
程序流程控制主要分为三种
- 顺序控制
- 分支控制
- 循环控制
2.3.1 顺序控制
程序从上到下逐行执行,中间没有任何判断和跳转(默认的控制顺序)
graph LR
A(A语句)-->B(B语句)-->C(C语句)-->D(D语句)-->E(...)
2.3.2 分支控制
#单分支控制:
当条件满足时,执行表达式。
graph LR
A(if 语句)--> B{条件表达式}
B --true--> C(执行语句块)
C --> D(继续)
B --false----> D
**注意:**在 Go 中,条件表达式不能加括号,且结构体即使只有一句也必须加上大括号
if i := 5; i < 10 {
i++
}
#双分支控制:
当条件满足时,执行表达式。否则执行另一表达式
graph LR
A(if...else 语句)--> B{条件表达式}
B --true--> C(执行语句块1)
C --> D(继续)
B --false--> F(执行语句块2)
F --> D
**注意:**在 Go 中,不能让 else 语句另起一行
if i < 10 {
i++
} else {
i--
}
#多分支控制:
有条件满足时,执行该表达式。否则执行 else 语句或直接继续
graph LR
A(if...else if 语句)--> B{条件1}
B --true--> C(执行语句块1)
C --> D(继续)
B --false--> F{条件2}
F --true--> G(执行语句块2)
G --> D
F --false--> H{条件3}
H --true--> I(执行语句块3)
I --> D
H --false--> J(else 语句块)
J --> D
其中,else 语句块不是必须的。
if i < 10 {
i++
} else if i > 20 {
i--
} else {
i = 0
}
#switch 分支结构:
switch 语句用于基于不同条件执行不同动作。
每个 case 分支都是唯一的,从上到下逐一测试,直到匹配为止。
graph LR
A(switch 语句)--> B{表达式 a}
B -->b1[a == 表达式 1]--true--> C(语句块1)
b1 --false-->b2[a == 表达式 2]--true--> D(语句块2)
b2 --false-->b3[a == 表达式 3]--true--> E(语句块3)
b3--false--> F(default语句块)
C --> G(继续)
D --> G
E --> G
F --> G
C -.fallthrough.-> D
D -.fallthrough.-> E
E -.fallthrough.-> F
var i int
fmt.Scanln(&i)
switch i {
case 1, 4, 2 << 3:
fmt.Println("喵喵喵")
case 2:
fmt.Println("汪汪汪")
case 3:
fmt.Println("嗷嗷嗷")
default:
fmt.Println("滋滋滋")
}
注意事项:
-
case 后可以是一个表达式(常量、变量、有返回值的函数)
-
case 后各个表达式数据类型需和 switch 表达式数据类型一致
-
case 后可以有多个表达式,以
,
分隔 -
case 后的表达式若是常量值,则要求不能重复
-
case 后不需要加 break,default 语句可以省略
-
switch 后面可以不带表达式,此时 case 表达式数据类型是布尔值。类似于多个 if…else 分支使用
-
(不推荐)switch 后可以直接声明 / 定义一个变量,并以
;
结束 -
在 case 语句块添加 fallthrough,则会穿透执行下一个 case 语句块
-
type switch 可以用于判断某个 interface 的变量类型
switch i := x.(type) { case int: fmt.Println("是 int 类型") case bool: fmt.Println("是 bool 类型") }
-
在 case 语句块添加 fallthrough,则会穿透执行下一个 case 语句块
switch i := 2; i { case 1: case 2: fallthrough case 3: }
fallthrough 必须出现在 case 块的最后,且该 case 块不能是最后一个 case 块
不允许在 type switch 中使用 fallthrough
2.3.3 循环控制
基本语法:
for 循环变量初始化; 循环条件; 循环变量迭代 {
循环操作
}
graph LR
A(for 循环语句) --> F[循环变量初始化] --> B{循环条件} --false--> D(继续)
B --true--> C(循环操作) --> E[循环变量迭代] --> B
for 循环四个要素:循环变量初始化、循环的条件、循环的操作、循环变量迭代
所有循环开始前仅一次进行初始化。直到循环条件变为 false 前,执行循环操作。每轮循环结束后,进行循环变量迭代。
可以把 变量初始化 和 循环变量迭代 写在其他位置。循环条件为空时,默认无限循环
#for-range
Golang 提供 for-range 方式,以便于遍历字符串和数组
var str string = "辟邪剑法"
for index, val := range str { // index 即下标,val 即值。使用 _ 忽略其中的一个
fmt.Printf("%d\t%c\n", index, val)
}
汉字占 3 字节。传统方法遍历字符串时,可能产生乱码。但 for-range 方式遍历时不会出错。
#while 和 do…while
Go 语言中没有 while 和 do…while 语法。通过 for 循环来模拟实现其效果。
/* 模拟 while */
for {
if (循环条件表达式) {
break;
}
循环操作
循环变量迭代
}
/* 模拟 do...while */
for {
循环操作
循环变量迭代
if (循环条件表达式) {
break;
}
}
2.4 跳转控制语句
#break
用于中止一个语句块的执行。用于中断当前 for 循环或跳出 switch 语句
graph LR
A(for 语句) --初始化--> B{循环条件} --false--> D(继续)
B --true--> c1(语句1) --> c2(语句2) --> c3(语句3) --> E[循环变量迭代] --> B
c1 --break--> D
-
break 默认会跳出最近的循环
-
break 语句出现在多层嵌套语句块中时,能通过标签指明要中止哪一层语句块
lable1: // 标签 for { for { fmt.Print("免疫 ") i++ if i >= 100 { break lable1 } else if i%10 == 0 { break } } fmt.Println() }
#continue
在循环中出现。用于结束本次循环,继续下一次循环
graph LR
A(for 语句) --初始化--> B{循环条件} --false--> D(继续)
B --true--> c1(语句1) --> c2(语句2) --> c3(语句3) --> E[循环变量迭代] --> B
c1 --continue--> E
- continue 默认会跳过最近的循环
- continue 语句出现在多层嵌套语句块中时,能通过标签指明要跳过哪一层循环
#goto
可以无条件地转移到程序中指定的行
- goto 语句通常与条件语句配合使用,以实现条件转移,跳出循环体等功能。
- 一般不建议使用 goto 语句,以免造成流程混乱
#return
用于方法或函数中。表示跳出所在的方法或函数
graph LR
A(调用方法A) --> B(语句a)
subgraph 方法A
B --> C(语句b) --> D(语句c) --> E(语句d)
end
E --执行完毕--> F(继续)
C --return--> F
如若写在主方法,会直接跳出程序