讲解

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。