Range
range周遊各種資料結構中的元素,本質上是Go内置的疊代器。
package main
import "fmt"
func main() {
// 疊代一個slice,對元素求和
nums := []int{2, 3, 4}
sum := 0
// range函數有傳回值,如果是疊代slice,則傳回index和value
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}
// 疊代map,則傳回key和value
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
// 僅疊代map的keys,傳回key
for k := range kvs {
fmt.Println("key:", k)
}
// 疊代字元串,傳回char的index和char對應的字元編碼
// g的ascii碼為103,o的ascii碼為111
for i, c := range "go" {
fmt.Println(i, c)
// 還原為字元串
fmt.Println(i, string(c))
}
}
上面程式的輸出:
$ go run range.go
sum: 9
index: 1
a -> apple
b -> banana
key: a
key: b
0 103
1 111
周遊通道
對于通道來說,range 會一直阻塞直到通道關閉,每次疊代傳回通道中的下一個值。
ch := make(chan int)
go func() {
ch <- 1
ch <- 2
ch <- 3
close(ch)
}()
for v := range ch {
fmt.Println(v)
}
上面程式的輸出:
1
2
3
忽略傳回值
有時候我們隻需要周遊數組、切片、字元串、映射或通道中的值,而不需要用到下标或鍵。這時候可以使用空白辨別符 _ 來忽略下标或鍵。
s := []int{1, 2, 3}
for _, v := range s {
fmt.Println(v)
}
m := map[string]int{"foo": 1, "bar": 2, "baz": 3}
for k := range m {
fmt.Println(k)
}
ch := make(chan int)
go func() {
ch <- 1
ch <- 2
ch <- 3
close(ch)
}()
for range ch {
fmt.Println("received from channel")
}
上面程式的輸出:
1
2
3
foo
bar
baz
received from channel
received from channel
received from channel
在這個例子中,我們使用空白辨別符 _ 來忽略了數組、切片、字元串、映射和通道中的下标或鍵。
跳出疊代
在循環中,可以使用 break 關鍵字來跳出循環,或使用 continue 關鍵字來跳過目前疊代。
s := []int{1, 2, 3, 4, 5}
for _, v := range s {
if v == 3 {
break
}
fmt.Println(v)
}
m := map[string]int{"foo": 1, "bar": 2, "baz": 3}
for k, v := range m {
if k == "bar" {
continue
}
fmt.Println(k, v)
}
上面程式的輸出:
1
2
foo 1
baz 3
在這個例子中,我們使用 break 來在數組、切片、字元串、映射和通道中跳出循環,或使用 continue 來跳過目前疊代。
多元數組
如果需要周遊多元數組或切片,可以使用多個 range。每個 range 對應一個次元。
arr := [2][3]int{{1, 2, 3}, {4, 5, 6}}
for _, row := range arr {
for _, v := range row {
fmt.Println(v)
}
}
s := [][]int{{1, 2}, {3, 4, 5}, {6, 7, 8, 9}}
for _, row := range s {
for _, v := range row {
fmt.Println(v)
}
}
每日一Tip
需要注意的是,對于映射來說,range 的疊代順序是随機的。如果需要按照特定順序疊代映射的鍵或值,可以将其存儲到一個切片中,然後對切片進行排序或者自定義排序函數。