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 的迭代顺序是随机的。如果需要按照特定顺序迭代映射的键或值,可以将其存储到一个切片中,然后对切片进行排序或者自定义排序函数。