今年做个 Dig101 系列,挖一挖技术背后的故事。
Dig101: dig more, simplified more and know more
golang 常用的遍历方式,有两种:for 和 for-range。而 for-range 使用中有些坑常会遇到,今天我们一起来捋一捋。
文章目录
0x01 遍历取不到所有元素指针?
0x02 遍历会停止么?
0x03 对大数组这样遍历有啥问题?
0x04 对大数组这样重置效率高么?
0x05 对 map 遍历时删除元素能遍历到么?
0x06 对 map 遍历时新增元素能遍历到么?
0x07 这样遍历中起 goroutine 可以么?
0x01 遍历取不到所有元素指针?
如下代码想从数组遍历获取一个指针元素切片集合arr := [2]int{
1, 2}
res := []*int{}
for _, v := range arr {
res = append(res, &v)
}
//expect: 1 2
fmt.Println(*res[0],*res[1])
//but output: 2 2
答案是【取不到】 同样代码对切片[]int{1, 2}
或map[int]int{1:1, 2:2}
遍历也不符合预期。问题出在哪里?
通过查看go 编译源码[1]可以了解到, for-range 其实是语法糖,内部调用还是 for 循环,初始化会拷贝带遍历的列表(如 array,slice,map),然后每次遍历的v
都是对同一个元素的遍历赋值。也就是说如果直接对v
取地址,最终只会拿到一个地址,而对应的值就是最后遍历的那个元素所附给v
的值。对应伪代码如下:
// len_temp := len(range)
// range_temp := range
// for index_temp = 0; index_temp