switch 语句
本教程共 80 篇 · 第 18 篇 · 更新于 2026-07-27 · 约 7 分钟阅读
18. switch 语句
本节目标:掌握 Go switch 的各种用法,理解它和 C/Java switch 的关键区别,学会 fallthrough 的正确使用。
switch 基本语法
switch 是多分支选择语句,比一长串 if-else if 更清晰:
day := "Monday"
switch day {
case "Saturday", "Sunday":
fmt.Println("周末")
case "Monday":
fmt.Println("星期一")
case "Tuesday":
fmt.Println("星期二")
default:
fmt.Println("其他")
}
Go switch 的独特之处
Go 的 switch 和 C/Java 的有几个重要区别:
1. 默认不穿透
在 C/Java 里,每个 case 后面必须写 break,否则会继续执行下一个 case。Go 不需要:
switch x {
case 1:
fmt.Println("一")
// 自动 break,不会执行 case 2
case 2:
fmt.Println("二")
}
Go 默认每个 case 执行完就跳出,不会穿透到下一个 case。
2. case 值不必是常量
func main() {
x := rand.Intn(10)
switch x {
case 1:
fmt.Println("一")
case x * 2:
fmt.Println("等于两倍") // case 可以是表达式
default:
fmt.Println("其他")
}
}
3. case 值不必是整数
switch "hello" {
case "hi":
fmt.Println("hi")
case "hello":
fmt.Println("hello") // 匹配这个
default:
fmt.Println("unknown")
}
字符串、浮点数等都可以作为 case 值。
case 多值匹配
一个 case 可以匹配多个值,用逗号分隔:
switch day {
case "Saturday", "Sunday":
fmt.Println("周末")
default:
fmt.Println("工作日")
}
只要 day 等于 "Saturday" 或 "Sunday",就会匹配这个 case。
无表达式 switch
switch 后面可以不写表达式,相当于 switch true,每个 case 是一个条件:
score := 85
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
case score >= 70:
fmt.Println("中等")
case score >= 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
这和 if-else if 链等价,但更整洁。当你在判断一个值的多个范围时,用无表达式 switch 比一堆 if-else 更清晰。
fallthrough
如果你确实想穿透到下一个 case,用 fallthrough:
switch x {
case 1:
fmt.Println("一")
fallthrough
case 2:
fmt.Println("二")
fallthrough
case 3:
fmt.Println("三")
}
如果 x 是 1,输出:
一
二
三
fallthrough 会无条件跳到下一个 case 的代码块,不管下一个 case 的条件是否匹配。
Warning
fallthrough必须是 case 块的最后一条语句。不能放在中间,也不能用在 case 的最后(因为没有下一个 case 了)。
// 报错
switch x {
case 1:
fallthrough
fmt.Println("这行不会执行") // fallthrough 后面不能有语句
}
Tip实际开发中很少用
fallthrough。如果你发现需要用它,先想想是不是设计有问题。大部分场景下,多个 case 合并或函数调用能更好地解决问题。
switch 带初始化语句
和 if 一样,switch 也可以带初始化语句:
switch num := computeValue(); num {
case 0:
fmt.Println("零")
case 1:
fmt.Println("一")
default:
fmt.Println("其他")
}
num 的作用域只在 switch 块内。
switch 求值顺序
case 从上到下依次匹配,匹配到就停止:
switch x {
case 0:
fmt.Println("零")
case f(): // 如果 x==0,f() 不会被调用
fmt.Println("f()")
}
如果 x 等于 0,第一个 case 就匹配了,f() 不会被调用。这个特性可以用来做短路优化。
实际示例
根据类型判断
func describe(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("整数:%d\n", v)
case string:
fmt.Printf("字符串:%s\n", v)
case bool:
fmt.Printf("布尔:%t\n", v)
default:
fmt.Printf("未知类型:%T\n", v)
}
}
这种写法叫类型 switch,用于判断接口值的实际类型。接口和类型断言后面章节会详细讲。
根据星期几做不同操作
func dailyTask(day string) {
switch day {
case "Monday":
fmt.Println("开周会")
case "Tuesday", "Wednesday", "Thursday":
fmt.Println("写代码")
case "Friday":
fmt.Println("代码评审")
case "Saturday", "Sunday":
fmt.Println("休息")
default:
fmt.Println("无效的星期")
}
}
处理 HTTP 状态码
func handleStatus(code int) string {
switch code {
case 200:
return "OK"
case 301:
return "Moved Permanently"
case 400:
return "Bad Request"
case 404:
return "Not Found"
case 500:
return "Internal Server Error"
default:
return "Unknown"
}
}
switch 和 if-else if 的选择
| 场景 | 推荐 |
|---|---|
| 同一个变量的多个具体值 | switch |
| 不同的条件表达式 | if-else if |
| 范围判断(大于、小于) | 无表达式 switch 或 if-else if |
| 类型判断 | 类型 switch(必须用 switch) |
// 用 switch 更好
switch month {
case 1, 2, 3:
fmt.Println("第一季度")
case 4, 5, 6:
fmt.Println("第二季度")
}
// 用 if-else 更好
if age < 18 {
// ...
} else if hasPermission {
// ...
} else if isAdmin {
// ...
}
常见问题
忘了写 default
不是必须写 default,但建议写上,特别是当你的 switch 应该覆盖所有可能值时。default 可以帮你发现遗漏的情况。
case 重复
switch x {
case 1:
// ...
case 1: // 报错:duplicate case
// ...
}
同一个值不能出现在两个 case 里。
fallthrough 误用
switch x {
case 1:
fmt.Println("一")
fallthrough
case 2:
fmt.Println("二")
}
如果 x 不是 1 而是 2,只会输出 “二”,fallthrough 不会往回跳。fallthrough 只从匹配的 case 往下穿透。
学完这节你能做什么
- 写基本的 switch 语句
- 用 case 多值匹配简化代码
- 用无表达式 switch 替代 if-else 链
- 理解 fallthrough 的行为和限制
- 知道什么时候用 switch,什么时候用 if
下一节讲 for 循环。