--- 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 强制规则 > `{` 必须与前一句在同一行,否则编译报错。这不是风格偏好,是语法要求。