golang中for range的取地址操作陷阱介绍
作者:qauzy 时间:2024-04-23 09:36:39
Tips:for range创建了每个元素的副本,而不是直接返回每个元素的引用
例子1:
package main
import "fmt"
func main() {
slice := []int{0, 1, 2, 3}
myMap := make(map[int]*int)
for index, value := range slice {
myMap[index] = &value
}
fmt.Println("=====new map=====")
prtMap(myMap)
}
func prtMap(myMap map[int]*int) {
for key, value := range myMap {
fmt.Printf("map[%v]=%v\n", key, *value)
}
}
输出:
dotzdeMacBook-Pro-2:src dotz$ ./range
=====new map=====
map[0]=3
map[1]=3
map[2]=3
map[3]=3
例子2:
package main
import "fmt"
type Test struct {
name string
}
func (this *Test) Point() { // this 为指针
fmt.Println(this.name)
}
func main() {
ts := []Test{{"a"}, {"b"}, {"c"}}
for _, t := range ts {
defer t.Point() //输出 c c c
}
}
输出:
dotzdeMacBook-Pro-2:src dotz$ ./method
c
c
c
例子1 我们预期输出0,1,2,3,例子2 我们预期输出a,b, c,但两个例子的输出都不是我们预期的。
对于例子1,比较明显,执行了取地址操作,每次都取value变量的地址,所以最后map中的所有元素的值都是value变量的地址(引用),因为最后value被赋值为3,所有输出都是3.
对于例子2,隐晦一点,夹杂了defer和方法接收者的规则,但其实也和例子1一样,执行t.Point()时,得到的是t的地址(引用),for结束时,t被赋值为”c“的地址,main函数返回时,都在执行”c“的接收方法Point,所以输出都是”c".
补充:golang取地址操作采坑:for idx,item := range arr中的item是个独立对象
先看代码:
package main
import "fmt"
func main() {
type s struct {
A string
B int32
}
arr := []s{
{"123", 123},
{"456", 456},
{"789", 789},
}
m := make(map[string]*s)
for idx, item := range arr {
m[item.A] = &item
fmt.Printf("idx=%d, addr=%p, item addr=%p\n", idx, &arr[idx], &item)
}
for k, v := range m {
fmt.Printf("key=%s, v=%+v\n", k, v)
}
}
运行输出:
idx=0, addr=0xc00004e050, item addr=0xc0000044a0
idx=1, addr=0xc00004e068, item addr=0xc0000044a0
idx=2, addr=0xc00004e080, item addr=0xc0000044a0
key=123, v=&{A:789 B:789}
key=456, v=&{A:789 B:789}
key=789, v=&{A:789 B:789}
我傻傻的在循环中取item的地址,结果所有map中的值都指向最后一个!
看来item是一个独立对象,这个对象指向了数组中的对应元素。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持asp之家。如有错误或未考虑完全的地方,望不吝赐教。
来源:https://blog.csdn.net/idwtwt/article/details/87378419
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
mysql installer community 5.7.16安装详细教程
![](https://img.aspxhome.com/file/2023/1/115571_0s.png)
python mysql项目实战及框架搭建过程
![](https://img.aspxhome.com/file/2023/6/90716_0s.jpg)
Python可视化学习之seaborn绘制矩阵图详解
![](https://img.aspxhome.com/file/2023/3/90883_0s.jpg)
Python数学建模学习模拟退火算法旅行商问题示例解析
![](https://img.aspxhome.com/file/2023/4/115094_0s.png)
Python操作RabbitMQ服务器实现消息队列的路由功能
如何根据用户银行帐户余额的多少进行显式的提交或终止?
vue 登录滑动验证实现代码
![](https://img.aspxhome.com/file/2023/7/133067_0s.png)
Yahoo!上的小秘密
![](https://img.aspxhome.com/file/UploadPic/20078/23/200782395619331s.jpg)
python批量下载壁纸的实现代码
JavaScript日期工具类DateUtils定义与用法示例
![](https://img.aspxhome.com/file/2023/3/136833_0s.png)
PyQt5根据控件Id获取控件对象的方法
MySQL timestamp自动更新时间分享
浅谈Go语言中字符串和数组
重命名SQLServer数据库的方法
CSS制作滑动折叠的文字效果
OpenCV半小时掌握基本操作之色彩空间
![](https://img.aspxhome.com/file/2023/9/123509_0s.gif)