Go 控制流
本章将介绍 Go 语言中的控制流语句,包括条件语句和循环。
if 语句
基本语法
if 条件 {
// 条件为 true 时执行
}
示例
age := 18
if age >= 18 {
fmt.Println("成年了")
}
if-else 语句
age := 16
if age >= 18 {
fmt.Println("成年了")
} else {
fmt.Println("未成年")
}
if-else if-else 语句
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
简短语句
if 语句可以在条件前执行一个简短语句:
if age := 18; age >= 18 {
fmt.Println("成年了")
}
// age 在这里不可用
多条件判断
score := 75
attendance := true
if score >= 60 && attendance {
fmt.Println("通过")
}
常见错误
// ❌ 错误:条件必须是布尔值
if x := 10; x { // 编译错误
fmt.Println(x)
}
// ✅ 正确
if x := 10; x > 0 {
fmt.Println(x)
}
switch 语句
基本语法
switch 变量 {
case 值1:
// 匹配值1时执行
case 值2:
// 匹配值2时执行
default:
// 都不匹配时执行
}
示例
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
case 4:
fmt.Println("星期四")
case 5:
fmt.Println("星期五")
case 6, 7: // 多个值
fmt.Println("周末")
default:
fmt.Println("无效的日期")
}
多条件匹配
grade := 'B'
switch grade {
case 'A', 'a':
fmt.Println("优秀")
case 'B', 'b':
fmt.Println("良好")
case 'C', 'c':
fmt.Println("及格")
default:
fmt.Println("不及格")
}
switch 不带变量
age := 20
switch {
case age < 18:
fmt.Println("未成年")
case age >= 18 && age < 60:
fmt.Println("成年人")
default:
fmt.Println("老年人")
}
fallthrough
Go 的 switch 语句默认不会 fallthrough,如果需要继续执行下一个 case,使用 fallthrough:
score := 75
switch {
case score >= 90:
fmt.Println("优秀")
fallthrough
case score >= 80:
fmt.Println("良好")
fallthrough
case score >= 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
// 输出:
// 及格
注意
fallthrough 会无条件执行下一个 case,建议谨慎使用。
简短语句
switch day := getDay(); day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
default:
fmt.Println("其他")
}
for 循环
Go 只有一种循环结构 for,但可以用多种方式使用。
基本语法
for 初始化; 条件; 后置语句 {
// 循环体
}
标准 for 循环
// 打印 1 到 5
for i := 1; i <= 5; i++ {
fmt.Println(i)
}
省略初始化
i := 1
for ; i <= 5; i++ {
fmt.Println(i)
}
省略条件(死循环)
for {
fmt.Println("无限循环")
if condition {
break
}
}
省略所有(while 风格)
i := 1
for i <= 5 {
fmt.Println(i)
i++
}
break 和 continue
// break:跳出循环
for i := 1; i <= 10; i++ {
if i == 6 {
break // 打印 1-5
}
fmt.Println(i)
}
// continue:跳过本次循环
for i := 1; i <= 5; i++ {
if i == 3 {
continue // 跳过 3
}
fmt.Println(i)
}
// 输出: 1, 2, 4, 5
嵌套循环
// 打印九九乘法表
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d*%d=%d\t", j, i, i*j)
}
fmt.Println()
}
标签和跳转
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer // 跳出外层循环
}
fmt.Printf("(%d,%d)\n", i, j)
}
}
range 循环
range 用于遍历数组、切片、映射、字符串和通道。
遍历数组/切片
// 遍历数组
nums := []int{1, 2, 3, 4, 5}
for index, value := range nums {
fmt.Printf("索引: %d, 值: %d\n", index, value)
}
// 只需要值
for _, value := range nums {
fmt.Println(value)
}
// 只需要索引
for index := range nums {
fmt.Println(index)
}
// 省略索引和值
for range nums {
fmt.Println("迭代一次")
}
遍历字符串
str := "Hello, 世界"
for index, rune := range str {
fmt.Printf("索引: %d, 字符: %c, Unicode: %U\n", index, rune, rune)
}
// 输出:
// 索引: 0, 字符: H, Unicode: U+0048
// 索引: 1, 字符: e, Unicode: U+0065
// ...
// 索引: 7, 字符: 世, Unicode: U+4E16
// 索引: 10, 字符: 界, Unicode: U+754C
遍历映射
ages := map[string]int{
"张三": 25,
"李四": 30,
"王五": 28,
}
for name, age := range ages {
fmt.Printf("%s: %d岁\n", name, age)
}
// 只遍历键
for name := range ages {
fmt.Println(name)
}
// 只遍历值
for _, age := range ages {
fmt.Println(age)
}
// 遍历顺序随机
遍历通道
ch := make(chan int, 5)
for i := 0; i < 5; i++ {
ch <- i
}
close(ch)
for v := range ch {
fmt.Println(v)
}
跳转语句
goto
goto 可以跳转到同一个函数内的标签:
func main() {
i := 0
Loop:
for i < 10 {
if i == 5 {
i++
goto Loop // 跳转到 Loop 标签
}
fmt.Println(i)
i++
}
}
警告
过度使用 goto 会使代码难以理解和维护,建议尽量避免。
循环中的错误处理
// 使用闭包封装
func main() {
result, err := process()
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println("结果:", result)
}
func process() (int, error) {
for i := 0; i < 10; i++ {
if i == 5 {
return i, nil
}
}
return 0, errors.New("未找到")
}
常见模式
遍历查找
nums := []int{1, 3, 5, 7, 9}
target := 5
found := false
for _, num := range nums {
if num == target {
found = true
break
}
}
if found {
fmt.Println("找到目标")
} else {
fmt.Println("未找到")
}
计数
count := 0
for _, v := range []int{1, 2, 3, 4, 5} {
if v > 3 {
count++
}
}
fmt.Println("大于3的数量:", count)
过滤
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var evens []int
for _, n := range nums {
if n%2 == 0 {
evens = append(evens, n)
}
}
fmt.Println("偶数:", evens)
映射转换
nums := []int{1, 2, 3, 4, 5}
var doubled []int
for _, n := range nums {
doubled = append(doubled, n*2)
}
fmt.Println("翻倍:", doubled)
小结
- if 语句:条件判断,支持简短语句
- switch 语句:多条件分支,不需要 break
- for 循环:Go 只有 for 循环,支持多种形式
- range 循环:遍历数组、切片、映射、字符串、通道
- break 和 continue:控制循环流程
- goto:跳转语句(慎用)
练习
- 打印 1-100 中所有偶数
- 计算 1+2+3+...+100 的和
- 使用 switch 判断成绩等级
- 找出数组中的最大值和最小值
- 使用 range 遍历并打印 map 的键值对
- 实现一个简单的猜数字游戏