vault backup: 2026-06-07 12:14:39

This commit is contained in:
2026-06-07 12:14:39 +08:00
parent 1a72bc4d82
commit 7ce9b83218
61 changed files with 8409 additions and 14429 deletions
+112 -217
View File
@@ -1,295 +1,190 @@
---
tags:
- Go
- golang
- go基础语法
- 条件语句
- 流程控制
tags: [go, golang, go基础语法, 条件语句, 流程控制]
create time: 2026-06-07 15:00
---
# Go语言条件语句
# Go 语言条件语句
条件语句是编程语言中最基本也是最常用的语句之一,它让程序可以根据不同的条件执行不同的代码块。Go语言提供了灵活而强大的条件语句支持。
## 概述
## if 语句
Go 提供 `if` 和 `switch` 两种条件分支机制。本文聚焦 Go 与 C/Java 的不同设计:无括号、自动 break、类型 switch 等。
### 基本语法
Go语言中的if语句不需要使用括号将条件包含起来,但是程序体必须使用大括号。基本语法如下:
## 正文
### if:为什么 Go 不需要括号?
```go
if condition {
// code to execute if condition is true
age := 18
if age >= 18 {
fmt.Println("你已经成年了")
}
```
例如:
```go
package main
Go 的 `if` **不需要括号**,但 `{` 必须与 `if` 在同一行(这是 gofmt 强制规则)。这一设计的核心好处是:**避免经典的 "dangling else" 歧义**。
import "fmt"
func main() {
age := 18
if age >= 18 {
fmt.Println("你已经成年了")
}
}
```
运行结果:
```
你已经成年了
```
### if-else 语句
当条件不满足时,可以使用else执行另一段代码:
#### if-else if-else 链
```go
package main
import "fmt"
func main() {
score := 85
if score >= 90 {
fmt.Println("优秀")
} else {
fmt.Println("继续努力")
}
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
```
运行结果:
```
继续努力
```
### if-else if-else 语句
当需要判断多个条件时,可以使用if-else if-else结构:
> [!tip] 💡 初始化语句用法
> `if` 支持在条件前放一条初始化语句,变量的作用域仅限 if-else 块内:
```go
package main
import "fmt"
func main() {
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
if num := 9; num < 10 {
fmt.Println(num, "小于10")
}
```
运行结果:
```
良好
// num 在这里不可用 → 作用域被严格限制
```
### if 的特殊写法
Go语言支持在if条件判断之前执行一个简单的语句:
这个特性在错误处理中极为常见:
```go
package main
import "fmt"
func main() {
if num := 9; num < 10 {
fmt.Println(num, "小于10")
} else {
fmt.Println(num, "大于等于10")
}
// 注意:num变量的作用域仅在if-else语句块内
if err := doSomething(); err != nil {
log.Printf("操作失败: %v", err)
return err
}
```
运行结果:
```
9 小于10
// err 的作用域仅限于 if 块
```
## switch 语句
> [!question] ❓ 思考
> 如果 `doSomething()` 返回多个值,比如 `(result, err)`,你能用一行 if 同时接收并判断吗?
### 基本用法
switch语句是多条件判断的另一种选择,相比于if-else更加清晰和简洁。Go语言的switch比传统的C/C++语言更加灵活:
- 不需要写break语句,匹配到case后自动中断
- 可以使用任意类型作为条件值,不限于常量或整数
- case语句可以使用表达式
### switch:Go 的条件分支利器
与 C/C++ 不同,Go 的 `switch` 有几个关键改进:
| 特性 | Go vs C/C++ |
|------|------------|
| 自动 break | Go 匹配后**自动中断**,无需写 `break` |
| 任意类型 | 可以用 `string`、`struct` 等任意可比较类型 |
| 表达式 case | case 可以是表达式而非仅常量 |
| 无分号 | 不需要末尾分号 |
基本语法示例:
```go
package main
import "fmt"
func main() {
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
case 4:
fmt.Println("星期四")
case 5:
fmt.Println("星期五")
default: // 可选的默认分支,当所有case都不匹配时执行
fmt.Println("周末")
}
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
default:
fmt.Println("周末")
}
```
运行结果:
```
星期三
```
### switch的特殊用法
#### switch 的高级用法
**多值 case** — 一个 case 匹配多个值:
1. 一个case可以有多个值,多个值之间使用逗号分隔:
```go
switch day {
case 1, 2, 3, 4, 5: // 可以匹配多个值,只需要满足其中一个即可
case 1, 2, 3, 4, 5:
fmt.Println("工作日")
case 6, 7:
fmt.Println("周末")
}
```
2. 省略switch后的表达式,这种形式更接近于if-else结构:
**省略表达式** — 接近 if-else if 的效果:
```go
score := 85
switch { // 省略条件表达式,默认为true
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
case score >= 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
fmt.Println("其他")
}
```
3. fallthrough关键字:
Go语言中的switch默认带有break效果,但如果需要继续执行下一个case,可以使用fallthrough:
> [!note] 📝 这等价于 if-else if 链,但在分支较多时更易扩展。
**fallthrough** — 强制执行下一个 case(慎用):
```go
switch {
case score >= 60:
fmt.Println("及格")
fallthrough // 继续执行下一个case,不管下一个case的条件是否满足
fallthrough // 继续执行下一个 case,不管条件
case score >= 0:
fmt.Println("分数有效")
}
// 输出:
// 及格
// 分数有效
```
运行结果:
```
及格
分数有效
```
注意:fallthrough必须是case中的最后一条语句,并且会强制执行下一个case的代码块,而不判断条件。
4. switch可以用于类型判断:
> [!warning] ⚠️ fallthrough 陷阱
> `fallthrough` 必须是 case 中的**最后一条语句**,且会**无条件**跳到下一个 case 的代码块(不判断条件)。滥用会导致难以追踪的逻辑错误。
### 类型 switch
`switch` 还有一个独特能力:**判断 interface{} 的动态类型**。
```go
var x interface{} = 25.0
switch v := x.(type) {
case int:
fmt.Printf("x是整数,值为%d\n", v)
fmt.Printf("整数: %d\n", v)
case float64:
fmt.Printf("x是浮点数,值为%.2f\n", v)
case string:
fmt.Printf("x是字符串,值为%s\n", v)
default:
fmt.Printf("x的类型未知\n")
}
```
运行结果:
```
x是浮点数,值为25.00
```
### switch注意事项
1. case的值必须是唯一的,不能重复
2. 每个case默认带有break,不用显式写出
3. case后的表达式必须与switch的表达式类型一致
4. 使用fallthrough时要特别小心,确保逻辑正确
5. default分支可选,但建议添加以处理未考虑的情况
## 实际应用示例
### 1. 错误处理
```go
if err := doSomething(); err != nil {
// 处理错误
fmt.Println("发生错误:", err)
return
}
```
### 2. 类型判断
```go
var i interface{} = "Hello"
switch v := i.(type) {
fmt.Printf("浮点数: %.2f\n", v)
case string:
fmt.Printf("字符串: %s\n", v)
case int:
fmt.Printf("整数: %d\n", v)
case bool:
fmt.Printf("布尔值: %v\n", v)
default:
fmt.Printf("未知类型\n")
}
// 输出:浮点数: 25.00
```
### 3. 状态机
> [!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
type State int
// ✅ 正确:{ 与 if 同行
if condition {
doSomething()
}
const (
Idle State = iota
Running
Paused
Stopped
)
func handleState(state State) {
switch state {
case Idle:
fmt.Println("系统空闲中")
case Running:
fmt.Println("系统运行中")
case Paused:
fmt.Println("系统已暂停")
case Stopped:
fmt.Println("系统已停止")
}
// ❌ 错误:{ 换行
if condition
{
doSomething()
}
```
## 使用技巧和注意事项
1. 代码风格
- if和else后的`{`必须和if或else在同一行
- 优先使用正向逻辑,避免多重否定
- 优先处理错误情况,让主逻辑更清晰
2. 性能考虑
- 多条件判断时,将最可能满足的条件放在前面
- 对于多个条件的判断,考虑使用switch替代if-else链
3. 常见陷阱
- 注意if语句中初始化变量的作用域
- 不要在switch的case中漏写break(Go自动break)
- 使用fallthrough时要特别小心,确保逻辑正确
## 小结
条件语句是程序流程控制的基础,Go语言通过简洁的语法和一些特殊的设计,让条件语句的使用更加灵活和高效。掌握好条件语句的各种用法,对于编写清晰、可维护的代码至关重要。
记住:选择合适的条件语句形式,让代码逻辑更清晰,可读性更好。过于复杂的条件判断应考虑重构,可能需要重新设计数据结构或使用其他模式。
> [!warning] ⚠️ gofmt 强制规则
> `{` 必须与前一句在同一行,否则编译报错。这不是风格偏好,是语法要求。