5.1 if-else 結構

if 是用於測試某個條件(布爾型或邏輯型)的語句,如果該條件成立,則會執行 if 後由大括號括起來的代碼塊,否則就忽略該代碼塊繼續執行後續的代碼。

if condition {
    // do something    
}

如果存在第二個分支,則可以在上面代碼的基礎上添加 else 關鍵字以及另一代碼塊,這個代碼塊中的代碼只有在條件不滿足時纔會執行。if 和 else 後的兩個代碼塊是相互獨立的分支,只可能執行其中一個。

if condition {
    // do something    
} else {
    // do something    
}

如果存在第三個分支,則可以使用下面這種三個獨立分支的形式:

if condition1 {
    // do something    
} else if condition2 {
    // do something else    
}else {
    // catch-all or default
}

else-if 分支的數量是沒有限制的,但是爲了代碼的可讀性,還是不要在 if 後面加入太多的 else-if 結構。如果你必須使用這種形式,則把儘可能先滿足的條件放在前面。

即使當代碼塊之間只有一條語句時,大括號也不可被省略(儘管有些人並不贊成,但這還是符合了軟件工程原則的主流做法)。

關鍵字 if 和 else 之後的左大括號 { 必須和關鍵字在同一行,如果你使用了 else-if 結構,則前段代碼塊的右大括號 } 必須和 else-if 關鍵字在同一行。這兩條規則都是被編譯器強制規定的。

非法的 Go 代碼:

if x{
}
else {    // 無效的
}

要注意的是,在你使用 gofmt 格式化代碼之後,每個分支內的代碼都會縮進 4 個或 8 個空格,或者是 1 個 tab,並且右大括號與對應的 if 關鍵字垂直對齊。

在有些情況下,條件語句兩側的括號是可以被省略的;當條件比較複雜時,則可以使用括號讓代碼更易讀。條件允許是符合條件,需使用 &&、|| 或 !,你可以使用括號來提升某個表達式的運算優先級,並提高代碼的可讀性。

一種可能用到條件語句的場景是測試變量的值,在不同的情況執行不同的語句,不過將在第 5.3 節講到的 switch 結構會更適合這種情況。

示例 5.1 booleans.go

package main
import "fmt"
func main() {
    bool1 := true
    if bool1 {
        fmt.Printf("The value is true\n")
    } else {
        fmt.Printf("The value is false\n")
    }
}

輸出:

The value is true

注意事項 這裏不需要使用 if bool1 == true 來判斷,因爲 bool1 本身已經是一個布爾類型的值。

這種做法一般都用在測試 true 或者有利條件時,但你也可以使用取反 ! 來判斷值的相反結果,如:if !bool1 或者 if !(condition)。後者的括號大多數情況下是必須的,如這種情況:if !(var1 == var2)

當 if 結構內有 break、continue、goto 或者 return 語句時,Go 代碼的常見寫法是省略 else 部分(另見第 5.2 節)。無論滿足哪個條件都會返回 x 或者 y 時,一般使用以下寫法:

if condition {
    return x
}
return y

注意事項 不要同時在 if-else 結構的兩個分支裏都使用 return 語句,這將導致編譯報錯 function ends without a return statement(你可以認爲這是一個編譯器的 Bug 或者特性)。( 譯者注:該問題已經在 Go 1.1 中被修復或者說改進

這裏舉一些有用的例子:

  1. 判斷一個字符串是否爲空:
    • if str == "" { ... }
    • if len(str) == 0 {...}
  2. 判斷運行 Go 程序的操作系統類型,這可以通過常量 runtime.GOOS 來判斷(第 2.2 節)。

     if runtime.GOOS == "windows"     {
         .    ..
     } else { // Unix-like
         .    ..
     }
    

    這段代碼一般被放在 init() 函數中執行。這兒還有一段示例來演示如何根據操作系統來決定輸入結束的提示:

     var prompt = "Enter a digit, e.g. 3 "+ "or %s to quit."
    
     func init() {
         if runtime.GOOS == "windows" {
             prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")        
         } else { //Unix-like
             prompt = fmt.Sprintf(prompt, "Ctrl+D")
         }
     }
    
  3. 函數 Abs() 用於返回一個整型數字的絕對值:

     func Abs(x int) int {
         if x < 0 {
             return -x
         }
         return x    
     }
    
  4. isGreater 用於比較兩個整型數字的大小:

     func isGreater(x, y int) bool {
         if x > y {
             return true    
         }
         return false
     }
    

在第四種情況中,if 可以包含一個初始化語句(如:給一個變量賦值)。這種寫法具有固定的格式(在初始化語句後方必須加上分號):

if initialization; condition {
    // do something
}

例如:

val := 10
if val > max {
    // do something
}

你也可以這樣寫:

if val := 10; val > max {
    // do something
}

但要注意的是,使用簡短方式 := 聲明的變量的作用域只存在於 if 結構中(在 if 結構的大括號之間,如果使用 if-else 結構則在 else 代碼塊中變量也會存在)。如果變量在 if 結構之前就已經存在,那麼在 if 結構中,該變量原來的值會被隱藏。最簡單的解決方案就是不要在初始化語句中聲明變量(見 5.2 節的例 3 瞭解更多)。

示例 5.2 ifelse.go

package main

import "fmt"

func main() {
    var first int = 10
    var cond int

    if first <= 0 {

        fmt.Printf("first is less than or equal to 0\n")
    } else if first > 0 && first < 5 {

        fmt.Printf("first is between 0 and 5\n")
    } else {

        fmt.Printf("first is 5 or greater\n")
    }
    if cond = 5; cond > 10 {

        fmt.Printf("cond is greater than 10\n")
    } else {

        fmt.Printf("cond is not greater than 10\n")
    }
}

輸出:

first is 5 or greater cond is not greater than 10

下面的代碼片段展示瞭如何通過在初始化語句中獲取函數 process() 的返回值,並在條件語句中作爲判定條件來決定是否執行 if 結構中的代碼:

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

鏈接

results matching ""

    No results matching ""