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


猜你喜欢
- 通过exec可以执行动态Python代码,类似Javascript的eval功能;而Python中的eval函数可以计算Python表达式,
- 本文实例讲述了Python实现在matplotlib中两个坐标轴之间画一条直线光标的方法。分享给大家供大家参考。具体如下:看看下面的例子和效
- 本文实例讲述了Python有序查找算法之二分法。分享给大家供大家参考,具体如下:二分法是一种快速查找的方法,时间复杂度低,逻辑简单易懂,总的
- Request 对象在 scrapy 中 Request 对象代表着请求,即向服务器发送数据,该对象的构造函数原型如下所示:def __in
- 学了一天pygame,用python和pygame写一个简单的挡板弹球游戏GitHub:EasyBaffleBallGame# -*- co
- 1.0 获取浏览器窗口坐标 python目录可找到Webdriver.py 文件定义了get_window_rect()函数,可获取窗口的坐
- 本文实例讲述了Python日期时间Time模块。分享给大家供大家参考,具体如下:关于时间和日期模块python程序能用很多方式处理日期和时间
- 1、grid 布局说明:参数说明: sticky:在插件正常尺寸下,分配单元中多余的空间(如果没有声明属性,默认插
- 创建RandomWalk类为模拟随机漫步,我们将创建一个RandomWalk类,随机选择前进方向,这个类有三个属性,一个存储随机漫步的次数,
- 我们可以把表里每一个横行的数据,看成是不同的元组。在理解了这个概念后,昨天我们学了不少的namedtuple类,是否也能把元组转换成name
- 准备本文环境信息:软件版本CentOSCentOS 7.4MySQL8.0.x安装前先更新系统所有包sudo yum update安装1.
- 本文实现文件分类器的目的主要是为了将办公过程中产生的各种格式的文件完成整理。通过自定义需要整理的文件目录,将该目录下面的全部文件按照文件格式
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&
- 大家好,本期给大家带来Python字典11个方法的全面解析,希望对你有所帮助。字典(Dictionary)是Python提供的一种常用的数据
- 什么是RC4算法呢?也许您还不知道,没关系我为您找了下相关资料方便大家查看;RC4加密算法 RC4加密算法是大名鼎鼎的RSA三人组
- 一 什么是读写分离虽然知道处理大数据量时,数据库为什么要做读写分离,原因很简单:读写分离是MySQL优化的一方面,它可以提高性能,缓解数据库
- 简单构建一个项目,如下是mian.go文件package main// 条件编译-构建标签-如何使用IDE编译和识别func main()
- 刚开始接触Python,首先要解决的就是Python开发环境的搭建。目前比较好用的Python开发工具是PyCharm,他有社区办和专业版两
- 本文实例讲述了python网络编程之数据传输UDP实现方法。分享给大家供大家参考。具体分析如下:一、问题:你觉得网络上像msn,qq之类的工
- 这是一个非常简单的解决方案,柱状图中每一条柱都是一个 div,数据的大小呈现在 div 的宽或高上。 查看演示 例子下载实现的原理