流程控制
翻译整理自 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 1defer 与闭包
defer 的参数在 defer 语句执行时就求值:
i := 1
defer fmt.Println(i) // 1(不是 2)
i = 25. 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,足够覆盖绝大多数场景,可读性更高。