Files
cs-note/hzh/GolangStar/Go语言基础/Go语言条件句.md
T

191 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [go, golang, go基础语法, 条件语句, 流程控制]
create time: 2026-06-07 15:00
---
# Go 语言条件语句
## 概述
Go 提供 `if` 和 `switch` 两种条件分支机制。本文聚焦 Go 与 C/Java 的不同设计:无括号、自动 break、类型 switch 等。
## 正文
### if:为什么 Go 不需要括号?
```go
age := 18
if age >= 18 {
fmt.Println("你已经成年了")
}
```
Go 的 `if` **不需要括号**,但 `{` 必须与 `if` 在同一行(这是 gofmt 强制规则)。这一设计的核心好处是:**避免经典的 "dangling else" 歧义**。
#### if-else if-else 链
```go
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 块内:
```go
if num := 9; num < 10 {
fmt.Println(num, "小于10")
}
// num 在这里不可用 → 作用域被严格限制
```
这个特性在错误处理中极为常见:
```go
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 可以是表达式而非仅常量 |
| 无分号 | 不需要末尾分号 |
```go
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
default:
fmt.Println("周末")
}
```
#### switch 的高级用法
**多值 case** — 一个 case 匹配多个值:
```go
switch day {
case 1, 2, 3, 4, 5:
fmt.Println("工作日")
case 6, 7:
fmt.Println("周末")
}
```
**省略表达式** — 接近 if-else if 的效果:
```go
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
default:
fmt.Println("其他")
}
```
> [!note] 📝 这等价于 if-else if 链,但在分支较多时更易扩展。
**fallthrough** — 强制执行下一个 case(慎用):
```go
switch {
case score >= 60:
fmt.Println("及格")
fallthrough // 继续执行下一个 case,不管条件
case score >= 0:
fmt.Println("分数有效")
}
// 输出:
// 及格
// 分数有效
```
> [!warning] ⚠️ fallthrough 陷阱
> `fallthrough` 必须是 case 中的**最后一条语句**,且会**无条件**跳到下一个 case 的代码块(不判断条件)。滥用会导致难以追踪的逻辑错误。
### 类型 switch
`switch` 还有一个独特能力:**判断 interface{} 的动态类型**。
```go
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 中被自动转换为对应类型,可以直接使用。
```mermaid
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 的标准模式
### 代码风格要点
```go
// ✅ 正确:{ 与 if 同行
if condition {
doSomething()
}
// ❌ 错误:{ 换行
if condition
{
doSomething()
}
```
> [!warning] ⚠️ gofmt 强制规则
> `{` 必须与前一句在同一行,否则编译报错。这不是风格偏好,是语法要求。