1. 程式人生 > >Go 系列教程-3 基礎知識

Go 系列教程-3 基礎知識

Go 系列教程 —— 8. if-else 語句

if 是條件語句。if 語句的語法是

if condition {  
}

如果 condition 為真,則執行 { 和 } 之間的程式碼。

不同於其他語言,例如 C 語言,Go 語言裡的 { } 是必要的,即使在 { } 之間只有一條語句。

if 語句還有可選的 else if 和 else 部分。

if condition {  
} else if condition {
} else {
}

if-else 語句之間可以有任意數量的 else if。條件判斷順序是從上到下。如果 if 或 else if 條件判斷的結果為真,則執行相應的程式碼塊。 如果沒有條件為真,則 else 程式碼塊被執行。

讓我們編寫一個簡單的程式來檢測一個數字是奇數還是偶數。

package main

import (  
    "fmt"
)

func main() {  
    num := 10
    if num % 2 == 0 { //checks if number is even
        fmt.Println("the number is even") 
    }  else {
        fmt.Println("the number is odd")
    }
}

線上執行程式

if num%2 == 0 語句檢測 num 取 2 的餘數是否為零。 如果是為零則列印輸出 "the number is even",如果不為零則列印輸出 "the number is odd"。在上面的這個程式中,列印輸出的是 the number is even

if 還有另外一種形式,它包含一個 statement 可選語句部分,該元件在條件判斷之前執行。它的語法是

if statement; condition {  
}

讓我們重寫程式,使用上面的語法來查詢數字是偶數還是奇數。

package main

import (  
    "fmt"
)

func main() {  
    if num := 10; num % 2 == 0 { //checks if number is even
        fmt.Println(num,"is even") 
    }  else {
        fmt.Println(num,"is odd")
    }
}

線上執行程式

在上面的程式中,num 在 if 語句中進行初始化,num 只能從 if 和 else 中訪問。也就是說 num 的範圍僅限於 if else 程式碼塊。如果我們試圖從其他外部的 if 或者 else 訪問 num,編譯器會不通過。

讓我們再寫一個使用 else if 的程式。

package main

import (  
    "fmt"
)

func main() {  
    num := 99
    if num <= 50 {
        fmt.Println("number is less than or equal to 50")
    } else if num >= 51 && num <= 100 {
        fmt.Println("number is between 51 and 100")
    } else {
        fmt.Println("number is greater than 100")
    }

}

線上執行程式

在上面的程式中,如果 else if num >= 51 && num <= 100 為真,程式將輸出 number is between 51 and 100

獲取免費的 Golang 工具

一個注意點

else 語句應該在 if 語句的大括號 } 之後的同一行中。如果不是,編譯器會不通過。

讓我們通過以下程式來理解它。

package main

import (  
    "fmt"
)

func main() {  
    num := 10
    if num % 2 == 0 { //checks if number is even
        fmt.Println("the number is even") 
    }  
    else {
        fmt.Println("the number is odd")
    }
}

線上執行程式

在上面的程式中,else 語句不是從 if 語句結束後的 } 同一行開始。而是從下一行開始。這是不允許的。如果執行這個程式,編譯器會輸出錯誤,

main.go:12:5: syntax error: unexpected else, expecting }

出錯的原因是 Go 語言的分號是自動插入。你可以在這裡閱讀分號插入規則 https://golang.org/ref/spec#Semicolons

在 Go 語言規則中,它指定在 } 之後插入一個分號,如果這是該行的最終標記。因此,在if語句後面的 } 會自動插入一個分號。

實際上我們的程式變成了

if num%2 == 0 {  
      fmt.Println("the number is even") 
};  //semicolon inserted by Go
else {  
      fmt.Println("the number is odd")
}

分號插入之後。從上面程式碼片段可以看出第三行插入了分號。

由於 if{…} else {…} 是一個單獨的語句,它的中間不應該出現分號。因此,需要將 else 語句放置在 } 之後處於同一行中。

我已經重寫了程式,將 else 語句移動到 if 語句結束後 } 的後面,以防止分號的自動插入。

package main

import (  
    "fmt"
)

func main() {  
    num := 10
    if num%2 == 0 { //checks if number is even
        fmt.Println("the number is even") 
    } else {
        fmt.Println("the number is odd")
    }
}

線上執行程式

 

 

Go 系列教程 —— 9. 迴圈

迴圈語句是用來重複執行某一段程式碼。

for 是 Go 語言唯一的迴圈語句。Go 語言中並沒有其他語言比如 C 語言中的 while 和 do while 迴圈。

for 迴圈語法

for initialisation; condition; post {  
}

初始化語句只執行一次。迴圈初始化後,將檢查迴圈條件。如果條件的計算結果為 true ,則 {} 內的迴圈體將執行,接著執行 post 語句。post 語句將在每次成功迴圈迭代後執行。在執行 post 語句後,條件將被再次檢查。如果為 true, 則迴圈將繼續執行,否則 for 迴圈將終止。(譯註:這是典型的 for 迴圈三個表示式,第一個為初始化表示式或賦值語句;第二個為迴圈條件判定表示式;第三個為迴圈變數修正表示式,即此處的 post )

這三個組成部分,即初始化,條件和 post 都是可選的。讓我們看一個例子來更好地理解迴圈。

例子

讓我們用 for 迴圈寫一個打印出從 1 到 10 的程式。

package main

import (  
    "fmt"
)

func main() {  
    for i := 1; i <= 10; i++ {
        fmt.Printf(" %d",i)
    }
}

Run in playground

在上面的程式中,i 變數被初始化為 1。條件語句會檢查 i 是否小於 10。如果條件成立,i 就會被打印出來,否則迴圈就會終止。迴圈語句會在每一次迴圈完成後自增 1。一旦 i 變得比 10 要大,迴圈中止。

上面的程式會打印出 1 2 3 4 5 6 7 8 9 10 。

在 for 迴圈中宣告的變數只能在迴圈體內訪問,因此 i 不能夠在迴圈體外訪問。

break

break 語句用於在完成正常執行之前突然終止 for 迴圈,之後程式將會在 for 迴圈下一行程式碼開始執行。

讓我們寫一個從 1 列印到 5 並且使用 break 跳出迴圈的程式。

package main

import (  
    "fmt"
)

func main() {  
    for i := 1; i <= 10; i++ {
        if i > 5 {
            break //loop is terminated if i > 5
        }
        fmt.Printf("%d ", i)
    }
    fmt.Printf("\nline after for loop")
}

Run in playground

在上面的程式中,在迴圈過程中 i 的值會被判斷。如果 i 的值大於 5 然後 break 語句就會執行,迴圈就會被終止。列印語句會在 for迴圈結束後執行,上面程式會輸出為

1 2 3 4 5  
line after for loop

continue

continue 語句用來跳出 for 迴圈中當前迴圈。在 continue 語句後的所有的 for 迴圈語句都不會在本次迴圈中執行。迴圈體會在一下次迴圈中繼續執行。

讓我們寫一個打印出 1 到 10 並且使用 continue 的程式。

package main

import (  
    "fmt"
)

func main() {  
    for i := 1; i <= 10; i++ {
        if i%2 == 0 {
            continue
        }
        fmt.Printf("%d ", i)
    }
}

Run in playground

在上面的程式中,這行程式碼 if i%2==0 會判斷 i 除以 2 的餘數是不是 0,如果是 0,這個數字就是偶數然後執行 continue 語句,從而控制程式進入下一個迴圈。因此在 continue 後面的列印語句不會被呼叫而程式會進入一下個迴圈。上面程式會輸出 1 3 5 7 9

更多例子

讓我們寫更多的程式碼來演示 for 迴圈的多樣性吧

下面這個程式打印出從 0 到 10 所有的偶數。

package main

import (  
    "fmt"
)

func main() {  
    i := 0
    for ;i <= 10; { // initialisation and post are omitted
        fmt.Printf("%d ", i)
        i += 2
    }
}

Run in playground

正如我們已經知道的那樣,for 迴圈的三部分,初始化語句、條件語句、post 語句都是可選的。在上面的程式中,初始化語句和 post 語句都被省略了。i 在 for 迴圈外被初始化成了 0。只要 i<=10 迴圈就會被執行。在迴圈中,i 以 2 的增量自增。上面的程式會輸出 0 2 4 6 8 10

上面程式中 for 迴圈中的分號也可以省略。這個格式的 for 迴圈可以看作是二選一的 for while 迴圈。上面的程式可以被重寫成:

package main

import (  
    "fmt"
)

func main() {  
    i := 0
    for i <= 10 { //semicolons are ommitted and only condition is present
        fmt.Printf("%d ", i)
        i += 2
    }
}

Run in playground

在 for 迴圈中可以宣告和操作多個變數。讓我們寫一個使用宣告多個變數來列印下面序列的程式。

10 * 1 = 10  
11 * 2 = 22  
12 * 3 = 36  
13 * 4 = 52  
14 * 5 = 70  
15 * 6 = 90  
16 * 7 = 112  
17 * 8 = 136  
18 * 9 = 162  
19 * 10 = 190
package main

import (  
    "fmt"
)

func main() {  
    for no, i := 10, 1; i <= 10 && no <= 19; i, no = i+1, no+1 { //multiple initialisation and increment
        fmt.Printf("%d * %d = %d\n", no, i, no*i)
    }

}

Run in playground

在上面的程式中 no 和 i 被宣告然後分別被初始化為 10 和 1 。在每一次迴圈結束後 no 和 i 都自增 1 。布林型操作符 && 被用來確保 i 小於等於 10 並且 no 小於等於 19 。

無限迴圈

無限迴圈的語法是:

for {  
}

下一個程式就會一直列印Hello World不會停止。

package main

import "fmt"

func main() {  
    for {
        fmt.Println("Hello World")
    }
}

如果你打算在 go playground 裡嘗試上面的程式,你會得到一個“過程耗時太長”的錯誤。請嘗試在你本地系統上執行,來無限的列印 “Hello World” 。

這裡還有一個 range 結構,它可以被用來在 for 迴圈中運算元組物件。當我們學習陣列時我們會補充這方面內容。

 

Go 系列教程 —— 10. switch 語句

 

switch 是一個條件語句,用於將表示式的值與可能匹配的選項列表進行比較,並根據匹配情況執行相應的程式碼塊。它可以被認為是替代多個 if else 子句的常用方式。

看程式碼比文字更容易理解。讓我們從一個簡單的例子開始,它將把一個手指的編號作為輸入,然後輸出該手指對應的名字。比如 0 是拇指,1 是食指等等。

package main

import (
    "fmt"
)

func main() {
    finger := 4
    switch finger {
    case 1:
        fmt.Println("Thumb")
    case 2:
        fmt.Println("Index")
    case 3:
        fmt.Println("Middle")
    case 4:
        fmt.Println("Ring")
    case 5:
        fmt.Println("Pinky")

    }
}

線上執行程式

在上述程式中,switch finger 將 finger 的值與每個 case 語句進行比較。通過從上到下對每一個值進行對比,並執行與選項值匹配的第一個邏輯。在上述樣例中, finger 值為 4,因此列印的結果是 Ring 。

在選項列表中,case 不允許出現重複項。如果您嘗試執行下面的程式,編譯器會報這樣的錯誤: main.go:18:2:在tmp / sandbox887814166 / main.go:16:7

package main

import (
    "fmt"
)

func main() {
    finger := 4
    switch finger {
    case 1:
        fmt.Println("Thumb")
    case 2:
        fmt.Println("Index")
    case 3:
        fmt.Println("Middle")
    case 4:
        fmt.Println("Ring")
    case 4://重複項
        fmt.Println("Another Ring")
    case 5:
        fmt.Println("Pinky")

    }
}

線上執行程式

預設情況(Default Case)

我們每個人一隻手只有 5 個手指。如果我們輸入了不正確的手指編號會發生什麼?這個時候就應該是屬於預設情況。當其他情況都不匹配時,將執行預設情況。

package main

import (
    "fmt"
)

func main() {
    switch finger := 8; finger {
    case 1:
        fmt.Println("Thumb")
    case 2:
        fmt.Println("Index")
    case 3:
        fmt.Println("Middle")
    case 4:
        fmt.Println("Ring")
    case 5:
        fmt.Println("Pinky")
    default: // 預設情況
        fmt.Println("incorrect finger number")
    }
}

線上執行程式

在上述程式中 finger 的值是 8,它不符合其中任何情況,因此會列印 incorrect finger number。default 不一定只能出現在 switch 語句的最後,它可以放在 switch 語句的任何地方。

您可能也注意到我們稍微改變了 finger 變數的宣告方式。finger 宣告在了 switch 語句內。在表示式求值之前,switch 可以選擇先執行一個語句。在這行 switch finger:= 8; finger 中, 先聲明瞭finger 變數,隨即在表示式中使用了它。在這裡,finger 變數的作用域僅限於這個 switch 內。

多表達式判斷

通過用逗號分隔,可以在一個 case 中包含多個表示式。

package main

import (
    "fmt"
)

func main() {
    letter := "i"
    switch letter {
    case "a", "e", "i", "o", "u": // 一個選項多個表示式
        fmt.Println("vowel")
    default:
        fmt.Println("not a vowel")
    }
}

線上執行程式

在 case "a","e","i","o","u": 這一行中,列舉了所有的母音。只要匹配該項,則將輸出 vowel

無表示式的 switch

在 switch 語句中,表示式是可選的,可以被省略。如果省略表示式,則表示這個 switch 語句等同於 switch true,並且每個 case 表示式都被認定為有效,相應的程式碼塊也會被執行。

package main

import (
    "fmt"
)

func main() {
    num := 75
    switch { // 表示式被省略了
    case num >= 0 && num <= 50:
        fmt.Println("num is greater than 0 and less than 50")
    case num >= 51 && num <= 100:
        fmt.Println("num is greater than 51 and less than 100")
    case num >= 101:
        fmt.Println("num is greater than 100")
    }

}

線上執行程式

在上述程式碼中,switch 中缺少表示式,因此預設它為 true,true 值會和每一個 case 的求值結果進行匹配。case num >= 51 && <= 100:為 true,所以程式輸出 num is greater than 51 and less than 100。這種型別的 switch 語句可以替代多個 if else 子句。

Fallthrough 語句

在 Go 中,每執行完一個 case 後,會從 switch 語句中跳出來,不再做後續 case 的判斷和執行。使用 fallthrough 語句可以在已經執行完成的 case 之後,把控制權轉移到下一個 case 的執行程式碼中。

讓我們寫一個程式來理解 fallthrough。我們的程式將檢查輸入的數字是否小於 50、100 或 200。例如我們輸入 75,程式將輸出75 is lesser than 100 和 75 is lesser than 200。我們用 fallthrough 來實現了這個功能。

package main

import (
    "fmt"
)

func number() int {
    num := 15 * 5 
    return num
}

func main() {

    switch num := number(); { // num is not a constant
    case num < 50:
        fmt.Printf("%d is lesser than 50\n", num)
        fallthrough
    case num < 100:
        fmt.Printf("%d is lesser than 100\n", num)
        fallthrough
    case num < 200:
        fmt.Printf("%d is lesser than 200", num)
    }

}

線上執行程式

switch 和 case 的表示式不一定是常量。它們也可以在執行過程中通過計算得到。在上面的程式中,num 被初始化為函式 number() 的返回值。程式執行到 switch 中時,會計算出 case 的值。case num < 100: 的結果為 true,所以程式輸出 75 is lesser than 100。當執行到下一句 fallthrough 時,程式控制直接跳轉到下一個 case 的第一個執行邏輯中,所以打印出 75 is lesser than 200。最後這個程式的輸出會是

75 is lesser than 100  
75 is lesser than 200

fallthrough 語句應該是 case 子句的最後一個語句。如果它出現在了 case 語句的中間,編譯器將會報錯:fallthrough statement out of place

這也是我們本教程的最後內容。還有一種 switch 型別稱為 type switch 。我們會在學習介面的時候再研究這個。