主题
第03章 流程控制 —— if、for、switch
本章目标:掌握 Go 的三大流程控制工具,能写出有判断、能循环的真实程序。
1. 流程控制的本质
🌰 生活化比喻:写程序就像写菜谱。
- 顺序执行:第一步、第二步、第三步……(默认)
- 条件判断:if 鸡蛋打散了,就 ……
- 循环执行:for 锅里水开之前,一直加柴
- 分支选择:switch 看食材是什么,决定怎么炒
2. if 语句
2.1 基本形式
go
if score >= 60 {
fmt.Println("及格")
} else if score >= 90 {
fmt.Println("优秀")
} else {
fmt.Println("不及格")
}注意:Go 中 if 后面不需要括号,但 { 必须紧贴条件。
2.2 if 的"小特权":初始化语句
go
if num, err := strconv.Atoi(s); err == nil {
fmt.Println("解析成功:", num)
} else {
fmt.Println("解析失败:", err)
}🌰 生活化比喻:相当于"先洗手,再吃饭"——num 和 err 只在 if 块内有效。
这是 Go 推荐的写法,能让变量作用域最小化。
3. for 循环:唯一的循环关键字
Go 没有 while,没有 do-while,只有一个 for,但可以变出多种花样。
3.1 三段式(C 风格)
go
for i := 0; i < 10; i++ {
fmt.Println(i)
}3.2 单条件(while 风格)
go
n := 0
for n < 100 {
n += 7
}3.3 死循环
go
for {
// 无限循环,直到 break
}3.4 range 遍历(最常用)
go
nums := []int{10, 20, 30}
for i, v := range nums {
fmt.Println(i, v)
}
m := map[string]int{"a": 1, "b": 2}
for key, value := range m {
fmt.Println(key, value)
}
s := "Hello"
for idx, r := range s {
fmt.Printf("%d=%c\n", idx, r)
}📊 配套图解:diagrams/for-styles.svg
3.5 break 与 continue
go
for i := 0; i < 10; i++ {
if i == 5 { break } // 直接跳出
if i % 2 == 0 { continue } // 跳过本次
fmt.Println(i)
}3.6 标签跳转(少用)
go
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i*j > 4 {
break outer // 跳出外层
}
}
}4. switch:比 if-else 更优雅
4.1 基本形式
go
switch day {
case "Mon", "Tue", "Wed", "Thu", "Fri":
fmt.Println("工作日")
case "Sat", "Sun":
fmt.Println("周末")
default:
fmt.Println("未知")
}4.2 Go 的 switch 不像 C:默认不穿透!
go
switch n {
case 1:
fmt.Println("一")
// 没写 break,但不会执行下一个 case!
case 2:
fmt.Println("二")
}🌰 生活化比喻:C 的 switch 像多米诺骨牌,撞倒第一张就连续倒;Go 像电梯,到一层就停。如果你真想"穿透",用 fallthrough:
go
switch n {
case 1:
fmt.Println("一")
fallthrough
case 2:
fmt.Println("二") // 1 也会触发这里
}4.3 没有条件的 switch(替代复杂 if-else)
go
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 60:
fmt.Println("及格")
default:
fmt.Println("挂科")
}🌰 这相当于 switch true {...},每个 case 都是布尔表达式。
4.4 类型 switch(第07章会深入讲)
go
switch v := x.(type) {
case int:
fmt.Println("整数", v)
case string:
fmt.Println("字符串", v)
default:
fmt.Println("未知类型")
}📊 配套图解:diagrams/switch-anatomy.svg
5. goto:能不用就不用
go
goto END
fmt.Println("这行不会执行")
END:
fmt.Println("跳过来了")⚠️ 不要用 goto ——破坏代码结构。Go 保留它主要是为了某些底层场景(如错误清理)。
6. 综合案例:FizzBuzz
go
package main
import "fmt"
func main() {
for i := 1; i <= 30; i++ {
switch {
case i%15 == 0:
fmt.Println("FizzBuzz")
case i%3 == 0:
fmt.Println("Fizz")
case i%5 == 0:
fmt.Println("Buzz")
default:
fmt.Println(i)
}
}
}经典面试题:1-100 数字,3 的倍数打印 Fizz,5 的倍数打印 Buzz,15 的倍数打印 FizzBuzz。这道题考察的就是流程控制。
7. 本章小结
✅ Go 的 if 不需要括号,但 { 必须同行
✅ if x := ...; cond { ... } 是 Go 推荐写法
✅ 只有 for,但能模拟 while、do-while、死循环
✅ for range 是遍历切片、map、字符串的标准方式
✅ switch 默认不穿透,需要 fallthrough 才穿透
✅ 用无条件 switch 替代长 if-else 链
✅ 不要用 goto,保留它只是历史包袱
📂 配套资源
- examples/01_if.go —— if 与初始化语句
- examples/02_for.go —— for 的四种写法
- examples/03_range.go —— range 遍历
- examples/04_switch.go —— switch 的多种用法
- examples/05_fizzbuzz.go —— 经典面试题
- demo.html —— 浏览器可视化演示
- interview.md —— 面试题精选