Go 之旅二: 流程控制語句

原文鏈接 http://ironxu.com/696

學習 A Tour of Go (中文參考 Go 之旅中文 ) 整理的筆記。介紹流程控制語句 for, if, else, switchdefer 的基本概念和使用。

1. for

$GOPATH/src/go_note/gotour/flowcontrol/for.go 源碼如下:

/**
 * go 語言for 循環
 */

package main

import (
    "fmt"
)

func main() {
    sum := 0
    for i := 0; i < 10; i ++ {
        sum += i
    }
    fmt.Println("sum:", sum) // sum: 45

    // 初始化語句和後置語句是可選的
    sum = 1
    for ; sum < 1000; {
        sum += sum
    }
    fmt.Println("sum:", sum) // sum: 1024

    // 去掉分號 `;`, `for` 是 Go 中的 `while`
    sum = 1
    for sum < 1000 {
        sum += sum
    }
    fmt.Println("sum:", sum) // sum: 1024
}

Go 只有一種循環結構:for 循環。基本的 for 循環由三部分組成,用分號隔開:

  • 初始化語句:在第一次迭代前執行
  • 條件表達式:在每次迭代前求值
  • 後置語句:在每次迭代的結尾執行

初始化語句通常爲一句短變量聲明,該變量聲明僅在 for 語句的作用域中可見。Go 的 for 語句後面沒有小括號,大括號 { } 則是必須的。

1.1 for 是 Go 中的 while

初始化語句和後置語句是可選的,此時你可以去掉分號 ;, for 是 Go 中的 while

// 掉分號 `;`, `for` 是 Go 中的 `while`
sum := 1
for sum < 1000 {
    sum += sum
}
fmt.Println("sum: ", sum) 

1.2 無限循環

如果省略循環條件,該循環就不會結束,循環成爲一個無線循環。

func main() {
    for {
    }
}

2. if else

$GOPATH/src/go_note/gotour/flowcontrol/if/if.go 源碼如下:

/**
 * go if 控制語句
 */

package main

import (
    "fmt"
    "math"
)

func sqrt(x float64) string {
    // 表達式外無需小括號
    if x < 0 {
        return sqrt(-x) + "i"
    }
    return fmt.Sprint(math.Sqrt(x))
}

func pow(x, n, lim float64) float64 {
    // 條件表達式前可以執行一個簡單的語句
    if v := math.Pow(x, n); v < lim {
        return v
    } else {
        // 表達式前執行簡單的語句,語句聲明的變量作用域僅在 if 和對應的 else 塊中使用
        fmt.Printf("%g >= %g\n", v, lim)
    }
    return lim
}

func main() {
    fmt.Println(sqrt(2), sqrt(-4))

    fmt.Println(
        pow(3, 2, 10),
        pow(3, 3, 20),
    )
}

Go 的 if 語句與 for 循環類似,表達式外無需小括號 ( ) ,而大括號 { } 則是必須的。

2.1 if 的簡短語句

for 一樣, if 語句可以在條件表達式前執行一個簡單的語句,該語句聲明的變量作用域僅在 if 和對應的 else 塊中使用。

func pow(x, n, lim float64) float64 {
    // 條件表達式前可以執行一個簡單的語句
    if v := math.Pow(x, n); v < lim {
        return v
    } else {
        // 表達式前執行簡單的語句,語句聲明的變量作用域僅在 if 和對應的 else 塊中使用
        fmt.Printf("%g >= %g\n", v, lim)
    }
    return lim
}

3. switch

$GOPATH/src/go_note/gotour/flowcontrol/switch/switch.go 源碼如下:

/**
 * go switch 控制語句
 */

package main

import (
    "fmt"
    "time"
)

func main() {
    switch i := 1; i {
    case 0:
        fmt.Println(0)
    case 1:
        fmt.Println(1)
        fallthrough // 除非以 fallthrough 語句結束,否則分支會自動終止
    default:
        fmt.Println(2)
    }
    // 以上代碼段輸出
    // 1
    // 2

    // 沒有條件的 switch
    t := time.Now()
    switch {
    case t.Hour() < 12:
        fmt.Println("早上好!")
    case t.Hour() < 17:
        fmt.Println("下午好!")
    default:
        fmt.Println("晚上好!")
    }
}

Go 語言switch 除非以 fallthrough 語句結束,否則分支會自動終止。switchcase 語句從上到下順次執行,直到匹配成功時停止。

沒有條件的 switchswitch true 一樣,這種形式能將一長串 if-then-else 寫得更加清晰。

4. defer

$GOPATH/src/go_note/gotour/flowcontrol/defer/defer.go 源碼如下:

/**
 * go defer 控制語句
 */

package main

import "fmt"

func print() {
    defer fmt.Println("world")
    fmt.Println("hello")
}

func main() {
    print()

    fmt.Println("counting")
    for i := 0; i < 10; i++ {
        defer fmt.Println(i)
    }
    fmt.Println("done")
    // counting
    // done
    // 9
    // 8
    // 7
    // 6
    // 5
    // 4
    // 3
    // 2
    // 1
    // 0
}

defer 語句會將函數推遲到外層函數返回之後執行。推遲調用的函數其參數會立即求值,但直到外層函數返回前該函數都不會被調用。推遲的函數調用會被壓入一個棧中。 當外層函數返回時,被推遲的函數會按照後進先出的順序調用。

參考

@剛剛小碼農

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章