/ Go 语言 for range 循环攻略 /
在 Go 语言中,for range 循环是非常常用的遍历方式,可以用来遍历数组、切片、字符串、map 等数据结构。合理运用 for range 可以使代码更加简洁高效。
本文将全面介绍 Go 语言中 for range 的相关用法,内容包括:
- range 基本用法
- range 的原理
- 遍历数组
- 遍历切片
- 遍历字符串
- 遍历 map
- 遍历 channel
- for range 的性能
- for range 的陷阱和最佳实践
通过详细的概念讲解、源码分析和示例代码,你可以深入理解 Go 语言 for range 的设计思想和工作机制,并能够熟练使用 for range 处理各种数据类型。
1
1. range 基本用法
Go 语言中可以使用 range 配合 for 循环来遍历数组、切片、字符串、map 及 channel 等,格式如下:
for key, value := range coll { //代码 }
range 返回集合的索引和值,key 是索引,value 是对应的值。
2
2. range 的原理
range 在底层是以指针形式遍历的:
for ptr, end := &coll[0], &coll[len(coll)]; ptr != end; ptr++ { // 指针ptr遍历 }
这样 range 完成了:
- 获取开始和结束指针
- 指针自增访问每个元素
- 返回 key 和 value
理解这一点,有助于分析 range 的行为。
3
3. 遍历数组
遍历数组可以直接通过 range:
for i, v := range [3]int{1, 2, 3} { fmt.Println(i, v) } // 0 1 // 1 2 // 2 3
range 返回数组索引和值。
4
4. 遍历切片
切片遍历也类似:设置标签
for i, v := range []string{"a", "b", "c"} { fmt.Println(i, v) } // 0 a // 1 b // 2 c
range 可以遍历各种类型的切片。
5
5. 遍历字符串
字符串在 Go 里是字节切片,也可以用 range 迭代:
for i, v := range "abc" { fmt.Println(i, string(v)) } // 0 a // 1 b // 2 c
6
6. 遍历 map
遍历 map 时,range 返回 key 和 value:
kvs := map[string]string{"a":"apple", "b":"banana"} for k, v := range kvs { fmt.Println(k, v) } // 随机顺序打印kv
注意 map 的遍历顺序是不确定的。
7
7. 遍历 channel
可以对一个 channel 使用 range 不断获取发送的值:
ch := make(chan int) // 发送者 go func() { ch <- 1 ch <- 2 close(ch) }() // 接收者 for v := range ch { fmt.Println(v) }
需要关闭 channel 来结束 range。
8
8. range 性能
range 每次遍历会生成迭代值的副本,如果元素较大会带来额外性能损耗:
for _, s := range slice { process(s) // 传入副本 }
可以传入索引遍历,避免值拷贝:
for i := range slice { process(slice[i]) // 传入原值 }
9
9. 陷阱和最佳实践
for range 使用时有一些需要注意的地方:
- 修改 slice 值时可能引发 Bug
- 遍历 map 时删除元素需注意
- channel 需要关闭
- 复用变量需小心
建议使用索引变量访问元素可以避免部分问题。
另外 range 代码块最好使用局部变量,而不是外部变量。
10
总结
通过本文可以全面了解 Go 语言中 for range 的用法细节。range 可以帮助我们非常方便地遍历各种数据结构,是 Go 语言编程中非常重要的一个设计。合理运用 range 可以使代码更简洁高效。