Menu

Golang switch case 语句:fallthrough 与多值匹配

Go 中的 switch 如何工作:case 默认不会贯穿,一个 case 可以列出多个值,没有条件的 switch 可以替代 if/else 链,带初始化语句的 switch,fallthrough 关键字,以及类型 switch 简介。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

switch 把一个值与一组 case 依次比较,执行第一个匹配的 case。和 C、Java、JavaScript 不同,Go 的 case 不会贯穿到下一个,所以不存在忘写 break 的问题。

case 从上到下依次检查,只有第一个匹配的 case 会执行。没有任何匹配时执行 default;它是可选的,可以出现在列表中的任何位置,不过按惯例放在最后。

一个 case 匹配多个值

case "sat", "sun": 匹配其中任意一个值。C 语言里用堆叠的空 case 实现的效果,Go 就是这样表达的。任何可比较的类型都可以:字符串、数字、rune、布尔值、指针,以及枚举之类的具名类型:

两个 case 的常量值相同会导致编译错误:

./main.go:10:7: duplicate case 1 (constant of type int) in expression switch
	./main.go:8:7: previous case

没有条件的 switch

省略表达式后,每个 case 都变成一个布尔判断。这是 Go 中比长长的 if/else if 链更简洁的写法:

switch { 是 switch true { 的简写。因为第一个为真的 case 胜出,所以顺序很重要:只有 bmi < 18.5 为假时才会走到 bmi < 25,因此每个 case 都可以假定上面的 case 都不成立。

带初始化语句的 switch

和 if 一样,switch 可以以一条简短语句开头。在那里声明的变量,作用域仅限于这个 switch:

初始化语句也可以和无条件 switch 结合使用:switch n := len(items); { case n == 0: ... }。

fallthrough

如果确实想继续执行下一个 case,就在 case 的最后一条语句写 fallthrough。它会把控制权转到下一个 case 的代码体,而不计算它的条件:

等级 2 会打印 write,然后打印 read,权限向下逐级累加。后面 case 的条件不会被检查:从 case 2 执行 fallthrough 之后,即使 level 是 2,case 1 也会执行。

fallthrough 的规则:

  • 它必须是 case 中的最后一条语句。
  • 它不能出现在最后一个 case 中:cannot fallthrough final case in switch。
  • 类型 switch 中不允许使用它。

实际上,Go 代码里很少用到 fallthrough。一个 case 匹配多个值已经满足了常见需求,而显式的函数调用通常也比一串 fallthrough 更清楚。

switch 中的 break

case 里的 break 会退出 switch。case 会自行结束,所以只有想提前离开某个 case 时才需要它。陷阱在于循环里的 switch:

没有 loop 标签时,break 只结束 switch,循环会继续处理 "c"。而 continue 总是指向外层的循环,因为 switch 不是循环。

按类型 switch

类型 switch 根据接口值的动态类型进行分支,使用特殊形式 v.(type):

在只有一个类型的 case 中,x 就是那个类型(在 string case 中可以用 len(x))。在列出多个类型的 case 中,x 仍然是接口类型。类型断言一节会详细讲解类型 switch 和 v.(T) 断言。

Go 的 switch 与其他语言的不同之处

行为C、Java、JavaScriptGo
贯穿到下一个 case默认如此只有用 fallthrough 时
每个 case 末尾的 break必须写不需要
一个 case 多个值堆叠空 casecase a, b, c:
case 的值(大多是)常量任意表达式,从上到下求值
switch 的值整数类型(C)任意可比较类型
没有 switch 表达式不允许switch { case cond: }

case 表达式不必是常量。case limit(), max + 1: 是合法的;它们按顺序求值,直到有一个匹配,所以后面的表达式可能永远不会执行。

穷尽性检查

Go 不会检查针对枚举的 switch 是否覆盖了所有值。可以加一个 default,对意料之外的值记录日志、返回错误或 panic,或者使用 exhaustive 检查工具(属于 golangci-lint),在构建时报告缺失的 case。

常见问题

Go 的 switch 会贯穿到下一个 case 吗?

不会。Go 的 case 在遇到下一个 case 时自动结束;你永远不需要写 break 来终止它。如果想让执行继续进入下一个 case 的代码体,就在该 case 的最后一条语句写 fallthrough。它会无条件跳转,不检查下一个 case 的条件。

Go 中如何在一个 case 里匹配多个值?

用逗号分隔列出它们:case "sat", "sun":。只要 switch 的值等于其中任意一个,这个 case 就会执行。这代替了 C 或 Java 中层层堆叠的空 case。

Go 中没有条件的 switch 是什么?

switch { case x < 0: ...; case x == 0: ...; default: ... }。switch 后面没有表达式时,每个 case 都是一个布尔条件,第一个为真的 case 会执行。这是替代长长的 if/else if 链的惯用写法。

Go 中 switch 里的 break 有什么作用?

它结束的是 switch,而不是外层的 for 循环。因为 case 会自行结束,所以很少需要它,但在循环里的 switch 中写 break、想要跳出循环的人常会因此踩坑。要跳出循环,请用带标签的 break 或 return。

Coddy 编程语言插图

和 Coddy 一起学编程

开始