go 的 switch 是值匹配优先、自动终止、支持类型断言的分支选择器,不接受布尔表达式,不隐式穿透;适用于明确值、互斥分支、无副作用或类型未知场景,否则应优先用 if。

switch 在 Go 里不是“增强版 if”,而是**值匹配优先、自动终止、支持类型断言的分支选择器**。它不接受任意布尔表达式,也不隐式穿透,强行套用其他语言习惯容易写出永远不触发的 case 或意外跳过逻辑。
case 只能匹配值或类型,不能写 a > 5 && a
Go 的 case 后必须是可比较的常量、变量、表达式(最终求值为同一类型),但**不能是任意布尔逻辑**。下面这段会编译报错:
switch x {
case x > 5 && x 5 && x
- 错误信息是
invalid case x > 5 && x ,不是语法警告,是硬性限制 - 想做范围判断,得用
switch true形式,每个case写完整布尔表达式 - 注意顺序:Go 从上到下匹配第一个为
true的分支,后续不再检查
用 switch true 替代 if-else 链时,顺序和覆盖要人工保证
这是最常用也最容易翻车的写法。比如判断成绩等级:
switch true {
case score >= 90:
grade = "A"
case score >= 80:
grade = "B"
case score >= 70:
grade = "C"
default:
grade = "F"
}
- 它依赖“先匹配大阈值”,因为
score >= 70会捕获所有 ≥70 的数,包括 95 —— 所以必须把高分段放前面 - 漏掉边界(如
score == 100)不会出错,但若写成score > 90就可能让 90 落进下一个 case - 如果条件里含函数调用(如
isValid(data) && hasPermission(user, data)),建议直接用if,避免重复执行或副作用不可控
type switch 是 interface 类型安全的唯一可靠方式
当你拿到一个 interface{} 或自定义接口变量,又不确定底层类型时,switch 是唯一推荐的运行时识别手段:
func describe(v interface{}) {
switch v.(type) {
case string:
fmt.Printf("string: %s\n", v)
case int, int64:
fmt.Printf("integer: %d\n", v)
case []byte:
fmt.Printf("bytes, len=%d\n", len(v.([]byte)))
default:
fmt.Printf("unknown type: %T\n", v)
}
}
-
v.(type)只能在switch中使用,不能单独写在 if 里 - 多个类型用逗号分隔(如
int, int64),语义是“任一匹配” - 不要在
case中对v直接做类型断言(如v.(string)),那会 panic;应先用switch分支,再在对应块内安全转换
fallthrough 不是默认行为,且只能向下穿透一级
Go 的 case 默认自带 break,想延续到下一个 case 必须显式写 fallthrough,而且它只作用于紧邻的下一个分支,不支持跨多级或条件穿透:
switch x {
case 1:
fmt.Print("one")
fallthrough // 会进入 case 2
case 2:
fmt.Print("two") // 这行一定会执行
case 3:
fmt.Print("three") // 这行不会执行,fallthrough 不传递
}
-
fallthrough后面不能跟default,否则编译失败 - 它不检查下一个
case的值是否匹配,纯粹是“无条件跳转到下一分支体” - 真实项目中极少需要,多数情况是设计缺陷的信号——该合并逻辑或重构函数
switch:值明确、分支互斥、无副作用、类型未知——满足其中两项以上才值得上;否则,老老实实写 if 更安全。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











