Go 程式設計教學:控制結構 (Control Structure) - 選擇 (Selection)

PUBLISHED ON SEP 14, 2017 — PROGRAMMING

    到目前為止,我們的程式都是依序執行;在程式中加入控制結構 (control structure) 後,程式就可以依條件決定是否要執行某區塊的程式碼,也可以重覆多次執行同區塊的程式碼,這時候,程式好像變聰明了。

    控制結構分為兩種,分別是:

    • 選擇 (selection):選擇性執行
    • 迭代 (iteration):重覆執行

    在本文中,我們會介紹 Go 可用的選擇控制結構。

    if

    條件控制的作用在判斷程式的狀態,符合特定條件時,才執行該區塊內的程式碼,使得程式可以依不同狀態改變其行為。if 在英文中原本就是「如果」的意思,大部分的程式語言都用 if 當關鍵字,Go 也不例外。

    如果我們用 Go 虛擬碼 (pseudocode) 表示如下:

    if condition {
        // Do something here.
    }
    

    以下是實例:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        x := 10
     
        if x > 0 {
            fmt.Println("x is larger than zero")
        }
    }
    

    除了單一的 if 外,還可以加入 else 區塊, 將其寫成虛擬碼如下:

    if condition {
        // Do something here.
    } else {
        // Do something here.
    }
    

    以下是實例:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        x := 3
     
        if x > 10 {
            fmt.Println("x is larger than 10")
        } else {
            fmt.Println("x is not larger than 10")
        }
    }
    

    另外,還可以加入一個或以上的 else if 區塊,將其寫成虛擬碼如下:

    if condition_a {
        // Do something_a here.
    } else if condition_b {
        // Do something_b here.
    } else {
        // Do something.
    }
    

    以下是實例:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        n := 0
     
        if n > 0 {
            fmt.Println("n is larger than zero.")
        } else if n < 0 {
            fmt.Println("n is smaller than zero.")
        } else {
            fmt.Println("n is equal to zero.")
        }
    }
    

    在使用多個 if 敘述時,若滿足了某一個條件,程式即會進入該條件所在的區塊,執行該區塊的程式碼,接著跳出。要注意這個特性,以免寫出語法對,但邏輯錯的程式。以下實例使用多個 else if

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        score := 88
     
        if score >= 90 {
            fmt.Println("A")
        } else if score >= 80 {
            fmt.Println("B")
        } else if score >= 70 {
            fmt.Println("C")
        } else if score >= 60 {
            fmt.Println("D")
        } else {
            fmt.Println("F")
        }
    }
    

    switch

    Go 提供 switch 做為另一個條件判斷的語法。基本上,switch 可視為一種語法糖 (syntactic sugar),因為所有的 switch 語法都可以用等效的 if 語法來代替,但適當地使用 switch 會使得程式碼比較簡潔,而 C 家族的程式語言都保留 switch 這個語法,所以 Go 也就將 switch 保留下來。

    switch 的 Go 虛擬碼如下:

    switch (value) {
    case a:
        // Do something_a
    case b:
        fallthrough  // Explict fallthrough in Go.
    case c:
        // Do something_c.
    default:
        // Do something.
    }
    

    以下程式判斷該程式執行當下所用的系統:

    package main
    
    import (
    	"fmt"
    	"runtime"
    )
    
    func main() {
    	fmt.Print("Go runs on ")
    	os := runtime.GOOS
    	switch os {
    	case "windows":
    		fmt.Println("Windows")
    	case "darwin":
    		fmt.Println("Mac")
    	case "linux":
    		fmt.Println("GNU/Linux")
    	default:
    		// freebsd, openbsd, plan9...
    		fmt.Printf("%s.", os)
    	}
    }
    

    在上例中,default 的意思是如果不符合其他選項,就使用這個選項,類似 else 敘述,不是必需的。如同 if 般,Go 的 switch 也是由上而下依序執行。見以下實例:

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	fmt.Println("When's Saturday?")
    
    	today := time.Now().Weekday()
    	switch time.Saturday {
    	case today + 0:
    		fmt.Println("Today.")
    	case today + 1:
    		fmt.Println("Tomorrow.")
    	case today + 2:
    		fmt.Println("In two days.")
    	default:
    		fmt.Println("Too far away.")
    	}
    }
    

    在 C 語言中,switch 有一個易引起錯誤的 switch「特性」叫 fallthrough,簡單的說,這是因為沒在 case 區塊尾端加入 break 敘述,執行到另一個 case 區塊的程式碼所引發的行為;雖然 fallthrough 是語法特性,也很容易變成 bug。在 Go 裡面,為了預防這個 bug,取消這個特性,如果程式設計者需要這個特性,需明確加上 fallthrough 敘述。見以下實例:

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	now := time.Now().Weekday()
    
    	switch now {
    	case time.Saturday:
    		fallthrough
    	case time.Sunday:
    		fmt.Println("Weekend")
    	case time.Friday:
    		fmt.Println("Thank God. It's Friday")
    	case time.Wednesday:
    		fmt.Println("Hump day")
    	default:
    		fmt.Println("Week")
    	}
    }
    

    switch 也可以不加變數,這時候,switch 就像是另一個 if。見以下實例:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	score := 88
    
    	switch {
    	case score >= 90:
    		fmt.Println("A")
    	case score >= 80:
    		fmt.Println("B")
    	case score >= 70:
    		fmt.Println("C")
    	case score >= 60:
    		fmt.Println("D")
    	default:
    		fmt.Println("F")
    	}
    }
    

    在這種情形下,使用 if 或是 switch 僅是個人偏好。

    在本文中,我們介紹 ifswitch 兩種條件控制的語法,建議讀者可以試著將本文的範例分別以 if 和 switch 改寫,就可以體會在什麼情形下使用何種語法較合適。在下一篇文章中,我們會介紹迴圈。

    comments powered by Disqus