讲解

if 是程序的第一块流程控制积木:条件为真就执行大括号里的代码。Go 的 if 有两个显著的外观特征:条件不用圆括号包起来,而大括号必须写(哪怕只有一行)。这两个规定消除了大量风格争论,也让代码更易读。

Go 的 if 支持一个其他语言少有的「初始化语句」:if n := len(s); n > 10 { ... }。分号前声明的变量只在整个 if-else 链内部有效,特别适合「先算个值、马上判断、之后不再需要」的场景——配合返回两个值的函数(如 map 取值、类型断言)非常顺手,还能避免变量泄漏到外层作用域被误用。

Go 没有三元运算符 x ? a : b,官方立场是三元表达式嵌套起来伤可读性,老老实实用 if-else。else if 链处理多分支时,条件从上往下短路执行,命中第一个为真的分支后其余不再判断,所以条件顺序要从严到宽排。简单的多值等值分支则该考虑下一章的 switch。

示例

基本的 if-else:

package main

import "fmt"

func main() {
	age := 20
	if age >= 18 {
		fmt.Println("成年人")
	} else {
		fmt.Println("未成年")
	}

	score := 88
	if score >= 90 {
		fmt.Println("优秀")
	} else if score >= 60 {
		fmt.Println("及格")
	} else {
		fmt.Println("不及格")
	}
}

带初始化语句的 if,变量只在分支内有效:

package main

import "fmt"

func grade(score int) string {
	if score >= 90 {
		return "优秀"
	} else if score >= 60 {
		return "及格"
	}
	return "不及格" // 走到这里一定是 60 以下,不用再写 else
}

func main() {
	fmt.Println(grade(92), grade(70), grade(45))

	if n := len([]int{1, 2, 3}); n > 2 {
		fmt.Println("切片长度超过 2:", n)
	}
	// 这里访问不到 n,作用域仅限 if 内部
}

常见坑

  • 给条件加圆括号:if (x > 0) 在 Go 里能编译但 gofmt 会帮你删掉括号,社区视为多余。反过来忘记大括号是直接编译错误。
  • 左大括号换行:Go 的分号是词法器自动插入的,if cond 换行再写 { 会被解析成语句结束,编译报错。Go 强制 K&R 风格:左大括号永远在行尾。
  • else if 链顺序颠倒:if score >= 60 写在 score >= 90 前面,90 分以上的人全被判成「及格」。范围条件从上到下必须由严到宽。
  • 在条件里做赋值:if x = 5 是编译错误(Go 的条件必须是布尔表达式),这在客观上消灭了把 == 误写成 = 的经典 bug,但也要注意条件里不能顺手赋值。
  • 滥用 if 初始化语句:初始化语句适合「临时算个值马上用」的场景,把复杂的多步逻辑塞进去会严重伤可读性,一行放不下就拆出来。

小结

if 条件无括号、大括号必须写、左大括号不换行;初始化语句让临时变量留在分支内;Go 没有三元运算符。下一节学习更适合多分支的 switch。