iT邦幫忙

2024 iThome 鐵人賽

DAY 7
1
Modern Web

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

【Day07】Golang 基礎語法 | 迴圈與迭代(For Loop)

  • 分享至 

  • xImage
  •  

在 Golang 中,for 是唯一的迴圈語法,雖然看起來不像其他語言中的 whiledo-while,但透過靈活的表現方式,for 也能完成相同的功能。接下來將會介紹 Golang 中 for 的用法,並比較與 while 迴圈的不同,同時探討如何有效避免過度複雜的迴圈邏輯。

基本的 For 迴圈

  • 在 Golang 中,for 迴圈的基本結構如下:
for 初始化語句; 條件判斷; 更新語句 {
    // 迴圈內的程式邏輯
}
  • 範例:
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

這樣的迴圈會從 i = 0 開始,當條件 i < 5 成立時會繼續執行,並在每次執行後將 i 加 1,直到條件不再成立。


Break 和 Continue

breakcontinue 是控制迴圈執行流程的重要語法。

  1. break:用來中止整個迴圈。
for i := 0; i < 10; i++ {
    if i == 5 {
        break  // 當 i 等於 5 時,結束迴圈
    }
    fmt.Println(i)
}
  1. continue:用來跳過本次迴圈的剩餘部分,直接進入下一次迭代。
for i := 0; i < 10; i++ {
    if i%2 == 0 {
        continue  // 如果 i 是偶數,跳過當次迴圈
    }
    fmt.Println(i)
}

迭代與遍歷:使用 Range

在 Golang 中,我們經常需要遍歷陣列、切片、字典等資料結構,這時候 range 可以讓程式碼更簡潔。

  • 遍歷一個切片(這會在下篇介紹更為詳細的觀點)
nums := []int{1, 2, 3, 4, 5}
for index, value := range nums {
    fmt.Printf("索引: %d, 值: %d\n", index, value)
}
</* Output: */>
鍵: a, 值: 1
鍵: b, 值: 2
鍵: c, 值: 3

它依次遍歷字典的每個項目,並印出每個鍵和值。

  • 遍歷字典(這會在第11天中介紹更為詳細的觀點)
dict := map[string]int{"a": 1, "b": 2, "c": 3}
for key, value := range dict {
    fmt.Printf("鍵: %s, 值: %d\n", key, value)
}
</* Output: */>
索引: 0, 值: 1
索引: 1, 值: 2
索引: 2, 值: 3
索引: 3, 值: 4
索引: 4, 值: 5

它逐一取出切片的每個元素,並印出其索引與值。

While 迴圈用法

在 Golang 中,for 可以模擬其他語言中的 while 迴圈。當省略初始化和更新語句時,for 的行為就像一個 while 迴圈。

  • while 的實現
i := 0
for i < 5 {  // 模擬 while 迴圈
    fmt.Println(i)
    i++
}

這樣的 for 迴圈沒有初始化語句和更新語句,單純依賴條件判斷,與其他語言的 while 十分相似。

使用場景的比較:

  • For 迴圈:適合用於有確定次數的迭代,如遍歷陣列、切片等。
  • While 迴圈 (模擬):適合不確定次數的迭代,直到某個條件達成為止。

需要去注意的地方

避免過度迴圈包裝

當迴圈邏輯變得複雜時,過度的包裝會讓程式碼難以閱讀與維護。此時,應考慮將部分邏輯抽取到函數中,保持迴圈內的邏輯簡單。

func processItem(item int) {
    // 處理單一項目邏輯
    fmt.Println("處理項目:", item)
}

nums := []int{1, 2, 3, 4, 5}
for _, num := range nums {
    processItem(num)  // 抽取複雜邏輯至獨立函數
}

如果不需要遍歷的 index 值時,也可以用 "_" 取代

避免對外部狀態的改變

這種改變會造成程式難以理解與除錯。例如,在迴圈內改變全域變數的值是一個常見的副作用,應盡量避免。

// FIXME: - 考慮將計算邏輯封裝在函數內,傳回計算結果
total := 0
nums := []int{1, 2, 3, 4, 5}
for _, num := range nums {
    total += num  // 改變外部變數 total
}
  • 在迴圈中,變數 total 是一個外部變數,並且在迴圈內被直接修改。這個迴圈不僅計算了總和,還影響了外部狀態(外部變數 total)。
// TODO: - 改善方式
func sum(nums []int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

nums := []int{1, 2, 3, 4, 5}
result := sum(nums)
fmt.Println(result)
  • 這段程式將邏輯封裝在 sum 函數內,total 是函數內部的變數,並不影響外部的狀態。讓程式碼更具可預測性和穩定性。

單一職責原則(SRP)

迴圈只應該處理數據計算,不應同時處理顯示邏輯、資料庫存取等工作。

// FIXME: - 迴圈內同時處理資料和顯示邏輯
for i := 0; i < len(data); i++ {
    processData(data[i])
    fmt.Println("處理中的資料:", data[i])  // 顯示邏輯不應與處理邏輯混合
}

// TODO: - 將顯示邏輯抽取至外部
func displayData(data int) {
    fmt.Println("處理中的資料:", data)
}

for i := 0; i < len(data); i++ {
    processData(data[i])  // 只專注於處理資料
}

總結

今天我們學習了 Golang 中唯一的迴圈語法 for,其靈活性可以模擬其他語言中的 while 迴圈。我們介紹了 for 迴圈的基本結構,並且展示了如何使用 breakcontinue 控制迴圈流程。同時,我們學到了如何透過 range 簡潔地遍歷切片和字典。還有,為了避免迴圈邏輯過於複雜,我們探討了如何將邏輯抽取到函數中,並遵循單一職責原則 (SRP),確保迴圈僅專注於執行單一的責任,保持程式簡潔、易於維護。


上一篇
【Day06】Golang 基礎語法 | 條件判斷與分支控制 (If-else 與 Switch)
下一篇
【Day08】Golang 基礎語法 | 陣列與切片(Arrays & Slices)
系列文
Go 快 Go 高效: 從基礎語法到現代Web應用開發21
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言