1. 基本 switch --- 匹配值
Go 的 switch 默认每个 case 自动 break,不需要手动写 break(与 C/Java 不同):
bash
package main
import "fmt"
func main() {
day := 3
fmt.Print("Day: ")
switch day {
case 1:
fmt.Println("Monday")
case 2:
fmt.Println("Tuesday")
case 3:
fmt.Println("Wednesday")
case 4:
fmt.Println("Thursday")
case 5:
fmt.Println("Friday")
case 6:
fmt.Println("Saturday")
case 7:
fmt.Println("Sunday")
default:
fmt.Println("Invalid day")
}
}
执行结果:
bash
Day: Wednesday
要点:
- switch day --- 匹配变量 day 的值,day=3 匹配 case 3
- 每个 case 结束后自动 break,不会继续执行下一个 case(Go 与 C/Java 最大的区别)
- default --- 所有 case 都不匹配时执行,相当于 else
- case 的值必须是可比较的类型(int、string、rune 等),且每个 case 的值必须不同
2. 多值匹配 --- 一个 case 匹配多个值
用逗号分隔,一个 case 可以匹配多个值:
bash
package main
import "fmt"
func main() {
grade := 'B' // rune 类型
fmt.Print("Grade performance: ")
switch grade {
case 'A', 'a':
fmt.Println("Excellence")
case 'B', 'b':
fmt.Println("Good")
case 'C', 'c':
fmt.Println("Average")
case 'D', 'd', 'F', 'f':
fmt.Println("Needs improvement")
default:
fmt.Println("Invalid grade")
}
}
执行结果:
bash
Grade performance: Good
要点:
- case 'A', 'a': --- 只要 grade 是 'A' 或 'a' 就匹配,相当于 grade == 'A' || grade == 'a'
- 这比写多个独立 case 更简洁,尤其在处理大小写、枚举值分组时很实用
- 'B' 是 rune 类型(int32 的别名),单引号表示字符,双引号表示字符串
- case 'D', 'd', 'F', 'f': --- D/d 和 F/f 合并为一个 case,逻辑上它们都是"需要改进"
3. 无表达式 switch --- 等价于 if-else if 链
switch {} 不带表达式,每个 case 写完整的条件表达式:
bash
package main
import "fmt"
func main() {
score := 85
fmt.Print("Score evaluation: ")
switch {
case score >= 90:
fmt.Println("Outstanding")
case score >= 80:
fmt.Println("Very Good")
case score >= 70:
fmt.Println("Good")
case score >= 60:
fmt.Println("Satisfactory")
default:
fmt.Println("Needs work")
}
}
执行结果:
bash
Score evaluation: Very Good
要点:
- switch {} 没有表达式,每个 case 是一个独立的布尔条件
- 等价于 if-else if-else 链,但比 if-else 链更清晰易读
- case 按顺序判断,第一个为 true 的 case 执行后自动 break
- score=85:score >= 90 为 false → score >= 80 为 true → 输出 "Very Good"
- default 等价于最终的 else
- 适用场景:范围判断、复杂条件分支(if-else 嵌套超过 3 层时推荐用 switch)
4. fallthrough --- 强制执行下一个 case
Go 的 switch 默认每个 case 自动 break。fallthrough 显式打破这个规则,强制继续执行下一个 case:
bash
package main
import "fmt"
func main() {
day := 1
fmt.Print("Day type: ")
switch day {
case 1:
fmt.Print("Start of work week, ")
fallthrough
case 2, 3, 4:
fmt.Println("Weekday")
case 5:
fmt.Println("TGIF!")
case 6, 7:
fmt.Println("Weekend")
}
}
执行结果(day=1):
bash
Day type: Start of work week, Weekday
要点:
- day=1 匹配 case 1,输出 "Start of work week, "
- fallthrough 强制跳到下一个 case(case 2, 3, 4),不管下一个 case 的条件是否匹配
- 所以继续输出 "Weekday" --- 注意 day=1 并不匹配 case 2, 3, 4,但 fallthrough 无条件继续
- fallthrough 只能出现在 case 的最后一行,不能放在中间
- fallthrough 只能跳到下一个 case,不能指定跳到某个特定 case(与 C 的 goto 不同)
- Go 设计者认为 fallthrough 容易导致 bug,所以默认不加,必须显式写才生效
- 实际中很少使用 fallthrough,大部分场景用多值匹配(知识点 2)替代
5. switch 初始化语句 --- switch init; value
与 if 类似,switch 可以在条件前加初始化语句,初始化的变量作用域仅限 switch 块:
bash
package main
import "fmt"
func main() {
score := 85
fmt.Print("Letter grade: ")
switch x := score / 10; x {
case 10, 9:
fmt.Println("A")
case 8:
fmt.Println("B")
case 7:
fmt.Println("C")
case 6:
fmt.Println("D")
default:
fmt.Println("F")
}
}
执行结果:
bash
Letter grade: B
要点:
- switch x := score / 10; x --- 分号前是初始化语句,分号后是 switch 表达式
- x := 85 / 10 = 8,匹配 case 8,输出 "B"
- x 的作用域仅限 switch 块内部,switch 外无法访问 x
- case 10, 9: --- 100分和90-99分都对应 A(多值匹配)
- 与 if init; condition {} 语法一致,都是 Go 的"先初始化再判断"模式
- 好处:避免在 switch 外声明只用一次的临时变量,保持代码紧凑
知识点总结
|-------------|--------------------------------|
| 知识点 | 关键概念 |
| 基本 switch | 默认自动 break,不需要手动写(与 C/Java 不同) |
| 多值匹配 | case 'A', 'a': |
| 无表达式 switch | switch {} |
| fallthrough | 强制继续执行下一个 case,不检查条件,必须显式写 |
| switch 初始化 | switch x := score/10; x |