go的switch默认不自动break,需显式fallthrough实现穿透,且仅限分支末尾;省略表达式时变为条件判断;case值须编译期常量;type switch专用于interface类型分支。

switch 不会自动 break,漏写 fallthrough 是高频错误
Go 的 switch 默认每个分支执行完就退出,不像 C/Java 那样需要显式 break。但反过来说,如果你真想“穿透”到下一个分支,必须手动写 fallthrough——而且它只能出现在分支末尾,不能加条件、不能隔语句。
常见错误现象:case 1: 后面忘了写 fallthrough,结果本该共享逻辑的两个分支被拆开执行;或者误以为 fallthrough 会跳到下一个 case 表达式求值(其实它直接跳进下一分支体,不管那个 case 值是否匹配)。
- 只有当前分支最后一条语句才能是
fallthrough -
fallthrough后面不能跟任何其他语句,否则编译报错:fallthrough statement out of place - 如果多个
case值要走同一段逻辑,推荐合并写法:case 1, 2, 3:,比依赖fallthrough更安全
switch 可以省略表达式,变成类似 if-else 的条件判断
当不提供 switch 后的表达式时,switch 就退化为按顺序求值 case 中布尔表达式的结构,每个 case 其实就是一个独立条件分支。
使用场景:处理带优先级的多条件判断(比如状态校验、权限检查),比嵌套 if 更扁平;也适合写成“短路判断链”,一旦某个 case 为 true 就停止后续判断。
立即学习“go语言免费学习笔记(深入)”;
-
case表达式类型必须是bool,不能是任意值(否则编译失败) - 和普通 switch 一样,不会自动穿透,也不支持
fallthrough(语法上允许,但语义无意义) - 注意变量作用域:每个
case是独立作用域,:=声明的变量不能跨 case 使用
示例:
switch {
case x > 0 && y > 0:
fmt.Println("第一象限")
case x < 0 && y > 0:
fmt.Println("第二象限")
default:
fmt.Println("坐标轴或原点")
}
case 值必须是编译期常量,动态值要用 if 或 map 查表
Go 要求所有 case 后的值在编译时就能确定,不支持运行时计算的变量、函数调用、甚至切片元素访问。这是为了保证分支跳转可静态分析,也是 switch 性能优于 if 链的基础。
容易踩的坑:把从配置读取的码值、HTTP 请求头里的字符串、数据库查出的状态码,直接塞进 case,结果编译不过,报错:case xxx in switch must be a constant。
- 如果值来自外部(如
req.Header.Get("X-Mode")),只能用if或预建map[string]func()查表 - 枚举型常量(
const定义的 iota)可以,但需确保它们是未加修饰的裸值(MyEnumA可以,MyEnumA + 1不行) - 字符串字面量可以,但拼接后的不行(
"a" + "b"编译期不可算,哪怕看着简单)
type switch 处理 interface{} 类型不确定时的分支逻辑
当变量类型是 interface{},又需要根据不同底层类型执行不同逻辑(比如解析 JSON raw message、泛型回调参数分发),就得用 switch v := x.(type) 这种 type switch 写法。
关键点在于:type switch 的 case 后不是值,而是类型名;且它只对 interface 类型有效,对具体类型(如 string)直接用普通 switch 即可。
-
case nil:必须单独写,用来判断 interface 是否为 nil(注意:底层值为 nil 但 interface 本身非 nil 的情况,不会进这个分支) - 不能混用普通值 case 和 type case(比如一个 switch 里既有
case 1:又有case string:),会编译报错 - 性能上,type switch 底层是反射+类型哈希查找,比普通 switch 慢;高频路径建议提前断言或用具体类型接收










