Go 程式設計教學:控制流程 (Control Structure) - 迴圈 (Loop)

PUBLISHED ON SEP 17, 2017 — PROGRAMMING

在上一篇文章中,我們介紹了條件敘述,透過條件敘述,可以讓程式好像有判斷能力般。接著,在本文中,我們會介紹另一個控制結構:迴圈。透過迴圈,可以重覆執行某個區塊內的程式碼,而不需重覆撰寫相同的程式碼。

Go 語言的迴圈只有一個關鍵字,就是 for。但是,Go 的迴圈實際上有三種語義:

  • 以條件判斷控制的迴圈,相當於大多數語言的 while
  • 以計數器 (counter) 控制的迴圈,相當於 C 風格的 for 迴圈
  • 使用迭代器 (iterator) 的迴圈,相當於某些語言的 foreach 或是 for … in

Go 僅使用一個關鍵字,依筆者推測,應該是想減少關鍵字的數量,降低學習者的負擔;然而,使用同一個關鍵字,卻有多個使用情境,對於初學者來說,反而容易混淆。這樣的設計是否比較好,端看個人的觀點。

使用條件判斷的 for

第一種 for 的使用方式,是搭配某個條件判斷,當符合條件時,才執行迴圈內的動作,否則就退出迴圈。以虛擬碼撰寫如下:

for condition {
    statement
}

見以下實例:

如果不加任何條件,則條件永遠為真,會變成無窮迴圈 (infinite loop)。見以下實例:

有時候,程式會刻意寫成無窮迴圈,,像是 GUI 程式的 event loop 或是電腦遊戲的 game loop ,但初學程式時所寫的無窮迴圈時常是程式寫錯所造成的。通常,無窮迴圈會搭配改變迴圈進行的語法,詳見後文。

使用計數器的 for

第二種 for 的使用方式,是搭配某個計數器,當計數器還沒走到底時,就會執行迴圈內的程式碼,直到計數器結束。

實例如下:

理論上,這兩種寫法是等效的,端看個人喜好而定。通常,如果明確知道迴圈執行的次數,使用第二種寫法會比較好;反之,則使用第一種寫法會比較好。

使用迭代器的 for

由於這種寫法會牽涉到容器 (collection) 的使用,我們暫不說明,將於後續文章中介紹。

改變迴圈流程

除了先前介紹的控制迴圈的方式外,Go 可以用額外的語法改變迴圈的進行。Go 提供以下三種方式:

  • break
  • continue
  • goto

我們將於下文中介紹這些語法。

break

使用 break,可以中斷迴圈,通常搭配條件敘述一起使用。如下例:

continue

使用 continue,可以跳過該語句剩下的敘述,繼續下一輪迴圈。如下例:

搭配標籤的 break 和 continue

breakcontinue 可以搭配標籤 (label) 使用,對於多重迴圈等情形可控制離開迴圈的方式。以下是一個略長的實例,我們待會兒會說明:

在本程式中,我們藉由亂數 (random number) 使程式的狀態每次都不同,增加程式的趣味性。亂數是指隨機出現的數字,在電腦中,我們通常是透過亂數函式庫來得到亂數。首先,我們要餵入一個種子,Go 程式會依據種子來運算出一個數字,通常是使用系統時間,讓每次算出來的數字皆不同,就會讓程式狀態每次皆不同。

註:一般的亂數產生器用在密碼學上強度不足,會造成安全的危害;若要將亂數用於密碼學,請用適用於密碼學的亂數產生器。

goto

goto 搭配標籤,可以跳轉到程式中任意的位置。在以下例子中,我們用 goto 模擬迴圈:

當然,上面的例子僅是展示用途,實務上不建議這樣寫。由於 goto 太過自由,很容易就寫出難以維護的程式碼,因此,儘量少用 goto 為宜。在 C 語言中,會使用 goto 來釋放系統資源,程式碼會比較簡潔;不過,在 Go 語言中有一個更好的替代語法,就是下一節要講的 defer

defer

defer 是一種 Go 特有的流程控制語法,defer 語句會自動延遲到程式結束前才執行。主要用來釋放系統資源,使語法更具可讀性。

實例:終極密碼

在學到條件敘述和迴圈後,就可以試著寫一些小程式。在本例中,我們用 Go 寫一個終機密碼遊戲。在我們的遊戲中,程式會從 1 至 100 中隨機選出一個數字,使用者要從中猜這個數字為何;為了提示使用者,數字的範圍會動態改變。實例如下,這個例子稍微長一點,我們稍後會說明:

在 Go 語言中,使用 scanner 物件取得字串。在本程式中,我們建立一個從標準輸入 (standard input) 接收字串的 scanner;接著,提示使用者輸入字串;當 scanner 得到字串後,使用 strconv 套件解析字串並轉為整數,若解析成功,則得到使用者猜測的數字,若解析失敗,則請使用者繼續猜。在程式的尾端,則會根據使用者猜測的數字動態更新下次猜測數字的範圍。

在讀過本文後,讀者應該已經學會控制敘述了,學到這個時候,就可以開始嘗試寫一些小型程式。在下一篇文章中,我們會開始介紹結構 (struct),透過結構,可以在單一變數中存入多個變數,也可以創造新的型別。

comments powered by Disqus