在 Go 裡,你可以搭配索引並使用 for 對 slice 進行疊代,也可以使用 range。range 還能讓你對 map 進行疊代。
每次疊代都會回傳兩個值:索引/鍵,以及該索引/鍵對應元素的副本。
對 slice 執行迴圈輕而易舉,順序也和預期的一樣。
xi := []int{10, 20, 30}
for i, x := range xi {
fmt.Println(i, x)
}
// outputs:
// 0, 10
// 1, 20
// 2, 30
對 map 進行疊代則會出現新的問題:順序變成隨機的。
hash := map[int]int{9: 10, 99: 20, 999: 30}
for k, v := range hash {
fmt.Println(k, v)
}
// outputs, for example:
// 99 20
// 999 30
// 9 10
上面的輸出看起來可能不太對,因為大家會預期在 map 宣告中排第一個的鍵/值組合 9 10 應該最先印出,而不是最後印出。
然而,map 本質上是無序的,並沒有所謂的第一個或最後一個鍵/值組合。
因此,對 map 的項目進行疊代時,項目的存取順序是隨機的,不會依循任何特定模式。
這表示上面的輸出是可能發生的,但你實際執行時得到的結果可能不同。
想了解更多,請參閱 Go 語言規格:range 子句。
在 Go 裡,未使用的變數會在建置時產生錯誤。 有時你只需要值,就像第一個範例那樣:
xi := []int{10, 20, 30}
for i, x := range xi {
fmt.Println(x)
}
// Go build failed: i declared but not used
你可以用 _ 取代 i,告訴編譯器我們不使用那個值:
xi := []int{10, 20, 30}
for _, x := range xi {
fmt.Println(x)
}
// outputs:
// 10
// 20
// 30
如果你只想印出索引,可以用 _ 取代 x,或是乾脆省略宣告:
xi := []int{10, 20, 30}
// for i, _ := range xi {
for i := range xi {
fmt.Println(i)
}
// outputs:
// 0
// 1
// 2
型別定義會建立一個新的具名型別,它和所有其他型別都不相同,即使底層型別一模一樣也一樣。
type File []bool
這裡的 File 指的是棋盤上單一的垂直行,通常標示為 A 到 H。這一行裡的每個格子都用一個布林值表示,標記該格是否被佔用。現在 File 定義好了,我們就可以在其他定義裡使用它:
type Chessboard map[string]File
board := Chessboard{
"A": File{true, false, true},
"B": File{false, true, false},
}
Chessboard 把行的識別碼對應到 File 值。每個 File 都是由布林值組成的 slice,代表某一行棋盤裡的格子。少了這些型別定義,board 就會是 map[string][]bool,這樣一來就更難理解我們實際表示的內容了。
身為西洋棋愛好者,你會想寫一個屬於自己的版本。 沒錯,網路上或許已經有許多現成的西洋棋實作,但你的版本會是獨一無二的!
棋盤上的每個方格都用一組字母與數字來標示:
A B C D E F G H
8 # _ _ _ # _ _ # 8
7 _ _ _ _ _ _ _ _ 7
6 _ _ _ _ # _ _ # 6
5 _ # _ _ _ _ _ # 5
4 _ _ _ _ _ _ # # 4
3 # _ # _ _ _ _ # 3
2 _ _ _ _ _ _ _ # 2
1 # _ _ _ _ _ _ # 1
A B C D E F G H
實作CountInFile(board Chessboard, file string) int函式。
它應該走訪 map,計算被佔據方格的總數。
回傳一個整數。
如果 map 中找不到指定的直行,就回傳零(0)。
CountInFile(board, "A")
// => 3
實作CountInRank(board Chessboard, rank int) int函式。
它應該走訪指定的橫列,計算被佔據方格的總數。
回傳一個整數。
如果指定的橫列不是有效的橫列(不在1到8之間,含),就回傳零(0)。
CountInRank(board, 2)
// => 1
實作CountAll(board Chessboard) int函式。
它應該計算棋盤上有多少個方格,並回傳一個整數。
由於你不需要檢查方格的內容,可以考慮使用 range 並同時省略index與value。
CountAll(board)
// => 64
實作CountOccupied(board Chessboard) int函式。
它應該計算棋盤上有多少個方格被佔據。
回傳一個整數。
CountOccupied(board)
// => 15