背景介绍
for range一个很容易踩的坑,记录一下。
现象描述
有问题的代码如下:
arr := []int{1, 2, 3}
myMap := make(map[int]*int)
for i, v := range arr {
myMap[i] = &v
}
for _, v := range myMap {
fmt.Println(*v)
}
上面这段代码执行结果是:
3
3
3
按理不是应该打印下面这个结果吗:
1
2
3
为什么结果不符合预期呢?
合理解释
上面的问题,就是for range有点坑的地方:
对于代码
for i, v := range arr
实际执行是:
- 声明变量i,v;
- 遍历arr,将第一个值1赋值给v,将v的地址myMap[0];
- 再将第二个值2赋值给v,将v的地址myMap[1];
- 再将第三个值3赋值给v,将v的地址myMap[2];
所以可以看到:
myMap[0]、myMap[1]、myMap[2]实际存储的都是同一个地址,
都是 遍历arr前声明好的变量v的地址,
所以打印出来的结果都是 最后放入v中的值3.
正确做法
知道了问题的本质原因后,解决方法也显而易见了:
将每次遍历的值赋值给新的变量,再将新变量的地址赋值给myMap[i];
代码
arr := []int{1, 2, 3}
myMap := make(map[int]*int)
for i, v := range arr {
vTmp := v // 关键!!!
myMap[i] = &vTmp
}
for _, v := range myMap {
fmt.Println(*v)
}
网友评论