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