鍍金池/ 教程/ GO/ 5.1 if-else 結(jié)構(gòu)
4.7 strings 和 strconv 包
13.6 啟動(dòng)外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫
13 錯(cuò)誤處理與測(cè)試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個(gè)例子:使用 Sorter 接口排序
?# 11.5 測(cè)試一個(gè)值是否實(shí)現(xiàn)了某個(gè)接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語(yǔ)言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運(yùn)行時(shí)異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實(shí)例
12.8 使用接口的實(shí)際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說(shuō)明
7.2 切片
8.0 Map
3.1 Go 開發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測(cè)試和基準(zhǔn)測(cè)試
6.8 閉包
4.9 指針
13.1 錯(cuò)誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過(guò) Git 打包和安裝
2.7 Go 運(yùn)行時(shí)(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動(dòng)態(tài)類型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識(shí)符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對(duì)調(diào)
6.11 計(jì)算函數(shù)執(zhí)行時(shí)間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開發(fā)環(huán)境與其它工具
13.8 測(cè)試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類型的切片
3.9 與其它語(yǔ)言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長(zhǎng)參數(shù)
13.9 用(測(cè)試數(shù)據(jù))表驅(qū)動(dòng)測(cè)試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫(kù)
3.3 調(diào)試器
4.5 基本類型和運(yùn)算符
?# 11.8 第二個(gè)例子:讀和寫
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計(jì)算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯(cuò)誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項(xiàng)目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類型斷言:如何檢測(cè)和轉(zhuǎn)換接口變量的類型
5.4 for 結(jié)構(gòu)
4.8 時(shí)間和日期
2.3 在 Linux 上安裝 Go
12 讀寫數(shù)據(jù)
6.12 通過(guò)內(nèi)存緩存來(lái)提升性能
9.1 標(biāo)準(zhǔn)庫(kù)概述
12.6 用切片讀寫文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯(cuò)誤的模式
3.2 編輯器和集成開發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測(cè)試多返回值函數(shù)的錯(cuò)誤
6.7 將函數(shù)作為參數(shù)
8.2 測(cè)試鍵值對(duì)是否存在及刪除元素
3.4 構(gòu)建并運(yùn)行 Go 程序
2.1 平臺(tái)與架構(gòu)
5.3 switch 結(jié)構(gòu)

5.1 if-else 結(jié)構(gòu)

if 是用于測(cè)試某個(gè)條件(布爾型或邏輯型)的語(yǔ)句,如果該條件成立,則會(huì)執(zhí)行 if 后由大括號(hào)括起來(lái)的代碼塊,否則就忽略該代碼塊繼續(xù)執(zhí)行后續(xù)的代碼。

if condition {
    // do something 
}

如果存在第二個(gè)分支,則可以在上面代碼的基礎(chǔ)上添加 else 關(guān)鍵字以及另一代碼塊,這個(gè)代碼塊中的代碼只有在條件不滿足時(shí)才會(huì)執(zhí)行。if 和 else 后的兩個(gè)代碼塊是相互獨(dú)立的分支,只可能執(zhí)行其中一個(gè)。

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

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

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

else-if 分支的數(shù)量是沒(méi)有限制的,但是為了代碼的可讀性,還是不要在 if 后面加入太多的 else-if 結(jié)構(gòu)。如果你必須使用這種形式,則把盡可能先滿足的條件放在前面。

即使當(dāng)代碼塊之間只有一條語(yǔ)句時(shí),大括號(hào)也不可被省略(盡管有些人并不贊成,但這還是符合了軟件工程原則的主流做法)。

關(guān)鍵字 if 和 else 之后的左大括號(hào) { 必須和關(guān)鍵字在同一行,如果你使用了 else-if 結(jié)構(gòu),則前段代碼塊的右大括號(hào) } 必須和 else-if 關(guān)鍵字在同一行。這兩條規(guī)則都是被編譯器強(qiáng)制規(guī)定的。

非法的 Go 代碼:

if x{
}
else {  // 無(wú)效的
}

要注意的是,在你使用 gofmt 格式化代碼之后,每個(gè)分支內(nèi)的代碼都會(huì)縮進(jìn) 4 個(gè)或 8 個(gè)空格,或者是 1 個(gè) tab,并且右大括號(hào)與對(duì)應(yīng)的 if 關(guān)鍵字垂直對(duì)齊。

在有些情況下,條件語(yǔ)句兩側(cè)的括號(hào)是可以被省略的;當(dāng)條件比較復(fù)雜時(shí),則可以使用括號(hào)讓代碼更易讀。條件允許是符合條件,需使用 &&、|| 或 !,你可以使用括號(hào)來(lái)提升某個(gè)表達(dá)式的運(yùn)算優(yōu)先級(jí),并提高代碼的可讀性。

一種可能用到條件語(yǔ)句的場(chǎng)景是測(cè)試變量的值,在不同的情況執(zhí)行不同的語(yǔ)句,不過(guò)將在第 5.3 節(jié)講到的 switch 結(jié)構(gòu)會(huì)更適合這種情況。

示例 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

注意事項(xiàng) 這里不需要使用 if bool1 == true 來(lái)判斷,因?yàn)?bool1 本身已經(jīng)是一個(gè)布爾類型的值。

這種做法一般都用在測(cè)試 true 或者有利條件時(shí),但你也可以使用取反 ! 來(lái)判斷值的相反結(jié)果,如:if !bool1 或者 if !(condition)。后者的括號(hào)大多數(shù)情況下是必須的,如這種情況:if !(var1 == var2)。

當(dāng) if 結(jié)構(gòu)內(nèi)有 break、continue、goto 或者 return 語(yǔ)句時(shí),Go 代碼的常見寫法是省略 else 部分(另見第 5.2 節(jié))。無(wú)論滿足哪個(gè)條件都會(huì)返回 x 或者 y 時(shí),一般使用以下寫法:

if condition {
    return x
}
return y

注意事項(xiàng) 不要同時(shí)在 if-else 結(jié)構(gòu)的兩個(gè)分支里都使用 return 語(yǔ)句,這將導(dǎo)致編譯報(bào)錯(cuò) function ends without a return statement(你可以認(rèn)為這是一個(gè)編譯器的 Bug 或者特性)。( 譯者注:該問(wèn)題已經(jīng)在 Go 1.1 中被修復(fù)或者說(shuō)改進(jìn)

這里舉一些有用的例子:

  1. 判斷一個(gè)字符串是否為空:
    • if str == "" { ... }
    • if len(str) == 0 {...}
  2. 判斷運(yùn)行 Go 程序的操作系統(tǒng)類型,這可以通過(guò)常量 runtime.GOOS 來(lái)判斷(第 2.2 節(jié))。

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

    這段代碼一般被放在 init() 函數(shù)中執(zhí)行。這兒還有一段示例來(lái)演示如何根據(jù)操作系統(tǒng)來(lái)決定輸入結(jié)束的提示:

      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. 函數(shù) Abs() 用于返回一個(gè)整型數(shù)字的絕對(duì)值:

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

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

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

if initialization; condition {
    // do something
}

例如:

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

你也可以這樣寫:

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

但要注意的是,使用簡(jiǎn)短方式 := 聲明的變量的作用域只存在于 if 結(jié)構(gòu)中(在 if 結(jié)構(gòu)的大括號(hào)之間,如果使用 if-else 結(jié)構(gòu)則在 else 代碼塊中變量也會(huì)存在)。如果變量在 if 結(jié)構(gòu)之前就已經(jīng)存在,那么在 if 結(jié)構(gòu)中,該變量原來(lái)的值會(huì)被隱藏。最簡(jiǎn)單的解決方案就是不要在初始化語(yǔ)句中聲明變量(見 5.2 節(jié)的例 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

下面的代碼片段展示了如何通過(guò)在初始化語(yǔ)句中獲取函數(shù) process() 的返回值,并在條件語(yǔ)句中作為判定條件來(lái)決定是否執(zhí)行 if 結(jié)構(gòu)中的代碼:

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

鏈接