流程控制

翻译整理自 A Tour of Go - Flow Control 与 Effective Go - Control Structures。

1. for 循环

Go 只有一种循环语句 for,没有 while、do-while:

// 经典 C 风格
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// 类 while 写法
n := 10
for n > 0 {
    n--
}

// 无限循环
for {
    break
}

range 迭代

遍历切片、map、字符串、channel:

nums := []int{10, 20, 30}
for index, value := range nums {
    fmt.Println(index, value)
}

for _, v := range nums { // 忽略索引
    fmt.Println(v)
}

2. if 语句

条件不需要括号,但 {} 必填:

if x < 0 {
    fmt.Println("negative")
} else if x == 0 {
    fmt.Println("zero")
} else {
    fmt.Println("positive")
}

if 简短语句

可在条件前执行初始化语句,变量作用域仅在 if-else 块内:

if num := compute(); num < 0 {
    fmt.Println("neg")
} else {
    fmt.Println(num)
}

3. switch 语句

Go 的 switch 默认每个 case 自动 break,无需手动写:

switch os := runtime.GOOS; os {
case "darwin":
    fmt.Println("macOS")
case "linux":
    fmt.Println("Linux")
default:
    fmt.Println(os)
}

无表达式 switch

相当于 if-else 链:

switch {
case x < 0:
    fmt.Println("neg")
case x == 0:
    fmt.Println("zero")
default:
    fmt.Println("pos")
}

fallthrough 强制穿透

switch n := 1; n {
case 1:
    fmt.Println("one")
    fallthrough
case 2:
    fmt.Println("two") // 即使 n=1 也会执行
}

4. defer 延迟调用

defer 注册的语句在函数返回前执行,常用于资源释放:

func ReadFile(path string) error {
    f, err := os.Open(path)
    if err != nil {
        return err
    }
    defer f.Close() // 函数返回前关闭文件

    // 处理文件...
    return nil
}

多个 defer 按 LIFO 顺序执行:

defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
// 输出:3 2 1

defer 与闭包

defer 的参数在 defer 语句执行时就求值:

i := 1
defer fmt.Println(i) // 1(不是 2)
i = 2

5. goto / break / continue

Loop:
for i := 0; i < 5; i++ {
    for j := 0; j < 5; j++ {
        if i*j > 6 {
            break Loop // 跳出外层
        }
    }
}
  • break:跳出当前循环或带标签的循环
  • continue:跳过本次
  • goto:跳转标签,实际工程中几乎不用

小结

Go 的控制流刻意简洁,只有 for/if/switch/defer,足够覆盖绝大多数场景,可读性更高。