讲解
switch 处理「一个值对多个候选」的分支,比一长串 else if 清爽得多。Go 的 switch 与 C 家族有本质区别:每个 case 执行完自动跳出,不需要写 break——这消灭了其他语言里「忘写 break 导致穿透」的经典事故。真的需要继续执行下一个 case 时,必须显式写 fallthrough。
case 后面可以一次列多个值,用逗号分隔:case 1, 2, 3:。default 分支处理所有没命中的情况,可以省略,位置也不强制在最后(但按惯例放最后)。switch 同样支持初始化语句:switch n := compute(); n { ... }。
还有一种「无表达式 switch」:switch 后面什么都不写,每个 case 就是一个布尔条件,效果等同 else if 链但结构更平整,是 Go 社区推荐的复杂条件写法。配合初始化语句 switch n := x; { case n > 90: ... } 可以写出非常清晰的范围判断。
示例
基本的值匹配与多值 case:
package main
import "fmt"
func main() {
day := 3
switch day {
case 1, 2, 3, 4, 5:
fmt.Println("工作日")
case 6, 7:
fmt.Println("周末")
default:
fmt.Println("无效输入")
}
ch := 'b'
switch ch {
case 'a', 'e', 'i', 'o', 'u':
fmt.Println("元音字母")
default:
fmt.Println("辅音字母")
}
}
无表达式 switch 与 fallthrough:
package main
import "fmt"
func describe(score int) string {
switch {
case score >= 90:
return "优秀"
case score >= 60:
return "及格"
default:
return "不及格"
}
}
func main() {
fmt.Println(describe(88), describe(59))
// fallthrough 强制执行下一个 case(无论条件)
switch n := 1; n {
case 1:
fmt.Print("一")
fallthrough
case 2:
fmt.Println("二")
}
}
常见坑
- 按 C 的习惯写 break:Go 的 case 自带跳出语义,写 break 是多余(虽然合法);反过来想要穿透必须显式 fallthrough,而它极少使用,用到时先想想是不是设计有问题。
- case 里写重复值:两个 case 都匹配同一个值会编译报错「duplicate case」。重构时合并 case 列表要小心去重。
- 以为无表达式 switch 能混值匹配:switch 后面没有表达式时,每个 case 必须是布尔条件;写了 case 1: 这种值会编译错误。两种形态二选一。
- fallthrough 误解为「重新判断下一个 case」:fallthrough 是无条件直接执行下一个 case 的代码块,不检查下一个 case 的条件。这也是它几乎不出现在生产代码里的原因。
- 在 switch 里处理复杂逻辑:case 代码块超过几行就该抽成函数,switch 的价值在于一眼看清分支结构。
小结
Go 的 switch 自动跳出、支持多值 case 与无表达式条件形态,fallthrough 显式穿透但罕用。下一节学习 Go 唯一的循环语句:for。