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

4.2 KiB
Raw Blame History

tags, create time
tags create time
go
golang
go基础语法
条件语句
流程控制
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 强制规则 { 必须与前一句在同一行,否则编译报错。这不是风格偏好,是语法要求。