iT邦幫忙

2024 iThome 鐵人賽

DAY 6
1
Modern Web

Go 快 Go 高效: 從基礎語法到現代Web應用開發系列 第 6

【Day06】Golang 基礎語法 | 條件判斷與分支控制 (If-else 與 Switch)

  • 分享至 

  • xImage
  •  

在 Go 語言中,條件判斷主要可以透過 if-elseswitch 來實現。這兩種結構各有其優勢,可以根據需求選擇使用。以下將為各位介紹這兩者的使用情境。

基本的 if-else

  • 在 Golang 中,if-else的基本結構如下:
if 條件判斷為真 {
    // 當條件為 true 時執行這裡
} else {
    // 當條件為 false 時執行這裡
}
  • 範例:
age := 21

if age >= 18 {
    fmt.Println("成人")
} else {
    fmt.Println("未成年")
}

過度複雜的例子(不建議):

if condition1 {
    // 條件 1 的情況下...
} else if condition2 {
    // 條件 2 的情況下...
} else if condition3 {
    // 條件 3 的情況下...
} else {
    // 其他條件的情況下...
}
// FIXME : - 錯誤示範
if condition1 {
    if condition2 {
        // do something else
        return
    }
    
    // do something
    return
}

// TODO: - 正確使用方式
if condition1 {
    // do something
    return
}
// 直接進行下一個條件判斷,避免多層包裝
if condition2 {
    // do something else
    return
}

進階用法:

  • 在 if 中進行計算或變數賦值:
package main

import (
	"fmt"
)

func main() {
	price := 120.0
	discount := 0.1
	threshold := 100.0

	// 在 if 判斷中直接計算折扣後的價格
	if finalPrice := price - (price * discount); finalPrice < threshold {
		fmt.Printf("最終價格 %g 小於 %g\n", finalPrice, threshold)
	} else {
		fmt.Printf("最終價格 %g >= %g\n", finalPrice, threshold)
	}

	// 此時還是可以返回原價,因為 finalPrice 僅在 if-else 內部可用
	fmt.Printf("原始價格:%g\n", price)
}
</* Output: */>
最終價格 108 < 100
原始價格:120

注意:

  • 清晰與簡單if-else 結構應保持簡單直觀,避免過度包裝。
    • 若出現多個 else if,則建議改用 switch 結構,讓條件邏輯更為清晰直觀。
      (我個人是覺得如果超過 1 個 else if 個人就會選擇改用 switch 來做判斷。)

switch

switch 可以讓程式更加結構化,尤其適合處理多個條件分支。它不需要多個 else if,當條件非常多時,它會比 if-else 更加直觀。

switch variable {
case value1:
    // 當變數等於 value1 時執行這裡
case value2:
    // 當變數等於 value2 時執行這裡
default:
    // 當變數不等於以上任一值時執行這裡
}
  • 範例:
day := "Monday"

switch day {
case "Monday":
    fmt.Println("今天是星期一")
case "Tuesday":
    fmt.Println("今天是星期二")
default:
    fmt.Println("未知的日期")
}
age := 21

switch {
case age < 18:
    fmt.Println("未成年")
case age >= 18 && age < 60:
    fmt.Println("成人")
default:
    fmt.Println("老年人")
}

開放封閉原則 (Open/Closed Principle, OCP)

當我們在 switch 結構中使用條件判斷時,應該避免在 switch 裡面直接硬編碼(hard-code)具體的條件或邏輯,因為這樣會導致當有新的需求或條件時,我們必須修改現有的 switch 方法。

  • 範例:

假設我們有一個簡單的計算機需要支援不同的數學運算,傳統的 switch 可能會這樣寫:

func calculate(operator string, a, b int) int {
    switch operator {
    case "+":
        return a + b
    case "-":
        return a - b
    case "*":
        return a * b
    case "/":
        return a / b
    default:
        fmt.Println("未知的運算符")
        return 0
    }
}

每當需要增加新的運算時(例如取模 %),你都必須修改這個 switch 結構來加入新的運算符邏輯,這就是「硬編碼」的方式。

  • 使用接口和結構體的改進版本:(這部分會在第9天做更為完整的介紹。)
type Operation interface {
    Calculate(a int, b int) int
}

type Add struct {}
func (Add) Calculate(a int, b int) int {
    return a + b
}

type Subtract struct {}
func (Subtract) Calculate(a int, b int) int {
    return a - b
}

type Multiply struct {}
func (Multiply) Calculate(a int, b int) int {
    return a * b
}

type Divide struct {}
func (Divide) Calculate(a int, b int) int {
    return a / b
}
  • 首先,我們可以定義一個接口 Operation,它代表一個通用的運算行為,然後為每個運算定義具體的結構實現。
func performOperation(operator string, a, b int) int {
    var op Operation

    switch operator {
    case "+":
        op = Add{}
    case "-":
        op = Subtract{}
    case "*":
        op = Multiply{}
    case "/":
        op = Divide{}
    default:
        fmt.Println("未知的運算符")
        return 0
    }

    return op.Calculate(a, b)
}

func main() {
    result := performOperation("+", 5, 3)
    fmt.Println("結果是:", result)
}
  • 接著,使用一個 switch 來根據運算符選擇不同的運算實現,但這次 switch 並不包含具體的計算邏輯,而是委託給對應的結構來處理。

為什麼這樣設計符合 OCP?

  • 對擴展開放:如果你要新增一個模組運算 %,你只需要定義一個新的結構 Modulo,實現 Operation 接口的 Calculate 方法,然後在 switch 中添加一個簡單的 case "%": op = Modulo{},而不需要修改任何原有的運算邏輯。

  • 對修改封閉:一旦你定義好了加法、減法等運算的結構實現,你不再需要修改它們的內部邏輯,只需在需要時擴展新的運算邏輯。


總結

今天我們學到了在 Go 語言中如何使用 if-elseswitch 進行條件判斷。if-else 適合簡單的邏輯,但當條件過多時,使用 switch 可以讓程式碼更加清晰易讀。除此之外,我們還介紹了「開放封閉原則 (OCP)」,使用接口和多態來避免硬編碼條件,讓程式對擴展開放、對修改封閉,增加新功能時不需要更改既有邏輯。


上一篇
【Day05】Golang 基礎語法 | 型別宣告與別名(Types & Alias)
下一篇
【Day07】Golang 基礎語法 | 迴圈與迭代(For Loop)
系列文
Go 快 Go 高效: 從基礎語法到現代Web應用開發21
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言