4 个常见的 range loop (for-each) 循环模式
基本的 for-each 循环(切片或数组)
a := []string{"Foo", "Bar"}
for i, s := range a {
fmt.Println(i, s)
}
0 Foo
1 Bar
- 范围表达式,
a
,在开始循环之前 计算一次。 - 将迭代值分配给相应的迭代变量,
i
和s
,就像赋值语句一样。 - 第二个迭代变量是可选的。
- 对于 nil 切片,迭代次数为 0。
字符串迭代:符文或字节
对于字符串,范围循环遍历 Unicode 代码点。
for i, ch := range "日本語" {
fmt.Printf("%#U starts at byte position %d\n", ch, i)
}
U+65E5 '日' starts at byte position 0
U+672C '本' starts at byte position 3
U+8A9E '語' starts at byte position 6
- 索引是 UTF-8 编码的代码点的第一个字节;
rune
类型的第二个值是代码点的值。 - 对于无效的 UTF-8 序列,第二个值将为 0xFFFD,并且迭代将前进单个字节。
要遍历单个字节,只需使用普通for循环和字符串索引:
const s = "日本語" for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) }
e6 97 a5 e6 9c ac e8 aa 9e
映射迭代:键和值
映射上的迭代顺序没有指定,也不能保证每次迭代都是相同的。
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
for k, v := range m {
fmt.Println(k, v)
}
two 2
three 3
one 1
- 如果在迭代过程中删除了尚未到达的映射条目,则不会生成该值。
- 如果在迭代过程中创建了映射条目,则可能会生成也可能不会生成该条目。
- 对于 nil 映射,迭代次数为 0。
通道迭代
对于通道,迭代值是在关闭之前在通道上发送的连续值。
ch := make(chan int)
go func() {
ch <- 1
ch <- 2
ch <- 3
close(ch)
}()
for n := range ch {
fmt.Println(n)
}
1
2
3
- 对于 nil 通道,范围循环永远阻塞。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: