4.2 KiB
4.2 KiB
tags, create time
| tags | create time | |||||
|---|---|---|---|---|---|---|
|
2026-06-07 15:00 |
Go 语言条件语句
概述
Go 提供 if 和 switch 两种条件分支机制。本文聚焦 Go 与 C/Java 的不同设计:无括号、自动 break、类型 switch 等。
正文
if:为什么 Go 不需要括号?
age := 18
if age >= 18 {
fmt.Println("你已经成年了")
}
Go 的 if 不需要括号,但 { 必须与 if 在同一行(这是 gofmt 强制规则)。这一设计的核心好处是:避免经典的 "dangling else" 歧义。
if-else if-else 链
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
[!tip] 💡 初始化语句用法
if支持在条件前放一条初始化语句,变量的作用域仅限 if-else 块内:
if num := 9; num < 10 {
fmt.Println(num, "小于10")
}
// num 在这里不可用 → 作用域被严格限制
这个特性在错误处理中极为常见:
if err := doSomething(); err != nil {
log.Printf("操作失败: %v", err)
return err
}
// err 的作用域仅限于 if 块
[!question] ❓ 思考 如果
doSomething()返回多个值,比如(result, err),你能用一行 if 同时接收并判断吗?
switch:Go 的条件分支利器
与 C/C++ 不同,Go 的 switch 有几个关键改进:
| 特性 | Go vs C/C++ |
|---|---|
| 自动 break | Go 匹配后自动中断,无需写 break |
| 任意类型 | 可以用 string、struct 等任意可比较类型 |
| 表达式 case | case 可以是表达式而非仅常量 |
| 无分号 | 不需要末尾分号 |
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
default:
fmt.Println("周末")
}
switch 的高级用法
多值 case — 一个 case 匹配多个值:
switch day {
case 1, 2, 3, 4, 5:
fmt.Println("工作日")
case 6, 7:
fmt.Println("周末")
}
省略表达式 — 接近 if-else if 的效果:
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
default:
fmt.Println("其他")
}
[!note] 📝 这等价于 if-else if 链,但在分支较多时更易扩展。
fallthrough — 强制执行下一个 case(慎用):
switch {
case score >= 60:
fmt.Println("及格")
fallthrough // 继续执行下一个 case,不管条件
case score >= 0:
fmt.Println("分数有效")
}
// 输出:
// 及格
// 分数有效
[!warning] ⚠️ fallthrough 陷阱
fallthrough必须是 case 中的最后一条语句,且会无条件跳到下一个 case 的代码块(不判断条件)。滥用会导致难以追踪的逻辑错误。
类型 switch
switch 还有一个独特能力:判断 interface{} 的动态类型。
var x interface{} = 25.0
switch v := x.(type) {
case int:
fmt.Printf("整数: %d\n", v)
case float64:
fmt.Printf("浮点数: %.2f\n", v)
case string:
fmt.Printf("字符串: %s\n", v)
default:
fmt.Printf("未知类型\n")
}
// 输出:浮点数: 25.00
[!info] ℹ️
x.(type)语法 这只在switch体内可用。v在每个 case 中被自动转换为对应类型,可以直接使用。
graph TD
A["interface{} 值"] --> B{"类型判断"}
B -->|"int"| C["case int"]
B -->|"float64"| D["case float64"]
B -->|"string"| E["case string"]
B -->|"其他"| F["default"]
if vs switch:如何选择?
[!tip] 💡 选择建议
- 2~3 个分支:用
if-else更直观- 3+ 个分支且比较同一变量:用
switch更清晰- 判断 interface{} 类型:只能用类型 switch
- 错误处理:
if err != nil是 Go 的标准模式
代码风格要点
// ✅ 正确:{ 与 if 同行
if condition {
doSomething()
}
// ❌ 错误:{ 换行
if condition
{
doSomething()
}
[!warning] ⚠️ gofmt 强制规则
{必须与前一句在同一行,否则编译报错。这不是风格偏好,是语法要求。