Go 语言条件语句

到目前为止,我们看到的 Go 程序都是从 main() 函数开始执行,然后按顺序执行该函数体中的代码。但我们经常会需要只有在满足一些特定情况时才执行某些代码,也就是说在代码里进行条件判断。针对这种需求,Go 提供了下面这些条件结构和分支结构:

if-else 结构

if 是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号括起来的代码块,否则就忽略该代码块继续执行后续的代码。

  1. if condition {
  2. // do something
  3. }

如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行。ifelse 后的两个代码块是相互独立的分支,只可能执行其中一个。

  1. if condition {
  2. // do something
  3. } else {
  4. // do something
  5. }

如果存在第三个分支,则可以使用下面这种三个独立分支的形式:

  1. if condition1 {
  2. // do something
  3. } else if condition2 {
  4. // do something else
  5. } else {
  6. // catch-all or default
  7. }

else-if 分支的数量是没有限制的,但是为了代码的可读性,还是不要在 if 后面加入太多的 else-if 结构。如果你必须使用这种形式,则把尽可能先满足的条件放在前面。

即使当代码块之间只有一条语句时,大括号也不可被省略(尽管有些人并不赞成,但这还是符合了软件工程原则的主流做法)。

关键字 ifelse 之后的左大括号 { 必须和关键字在同一行,如果你使用了 else-if 结构,则前段代码块的右大括号 } 必须和 else-if 关键字在同一行。这两条规则都是被编译器强制规定的。

非法的 Go 代码:

  1. if x{
  2. }
  3. else { // 无效的
  4. }

要注意的是,在你使用 gofmt 格式化代码之后,每个分支内的代码都会缩进 4 个或 8 个空格,或者是 1tab,并且右大括号与对应的 if 关键字垂直对齐。

在有些情况下,条件语句两侧的括号是可以被省略的;当条件比较复杂时,则可以使用括号让代码更易读。条件允许是符合条件,需使用 &&、||!,你可以使用括号来提升某个表达式的运算优先级,并提高代码的可读性。

一种可能用到条件语句的场景是判断变量的值,在不同的情况执行不同的语句:

  1. package main
  2. import "fmt"
  3. func main() {
  4. bool1 := true
  5. if bool1 {
  6. fmt.Printf("The value is true\n")
  7. } else {
  8. fmt.Printf("The value is false\n")
  9. }
  10. }

输出:The value is true

注意:这里不需要使用 if bool1 == true 来判断,因为 bool1 本身已经是一个布尔类型的值。

这种做法一般都用在判断 true 或者有利条件时,但你也可以使用取反 ! 来判断值的相反结果,如:if !bool1 或者 if !(condition)。后者的括号大多数情况下是必须的,如这种情况:if !(var1 == var2)

if 结构内有 breakcontinuegoto 或者 return 语句时,Go 代码的常见写法是省略 else 部分。无论满足哪个条件都会返回 x 或者 y 时,一般使用以下写法:

  1. if condition {
  2. return x
  3. }
  4. return y

注意:不要同时在 if-else 结构的两个分支里都使用 return 语句,这将导致编译报错 function ends without a return statement(你可以认为这是一个编译器的 Bug 或者特性)。(该问题已经在 Go 1.1 中被修复或者说改进 )

if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号):

  1. if initialization; condition {
  2. // do something
  3. }

例如:

  1. val := 10
  2. if val > max {
  3. // do something
  4. }

你也可以这样写:

  1. if val := 10; val > max {
  2. // do something
  3. }

但要注意的是,使用简短方式 := 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。最简单的解决方案就是不要在初始化语句中声明变量。

示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var first int = 10
  5. var cond int
  6. if first <= 0 {
  7. fmt.Printf("first is less than or equal to 0\n")
  8. } else if first > 0 && first < 5 {
  9. fmt.Printf("first is between 0 and 5\n")
  10. } else {
  11. fmt.Printf("first is 5 or greater\n")
  12. }
  13. if cond = 5; cond > 10 {
  14. fmt.Printf("cond is greater than 10\n")
  15. } else {
  16. fmt.Printf("cond is not greater than 10\n")
  17. }
  18. }

输出:

  1. first is 5 or greater
  2. cond is not greater than 10

下面的代码片段展示了如何通过在初始化语句中获取函数 process() 的返回值,并在条件语句中作为判定条件来决定是否执行 if 结构中的代码:

  1. if value := process(data); value > max {
  2. ...
  3. }