golang中的那些坑之迭代器中的指针使用

今天在编写代码的时候,遇到了一个莫名其妙的错误,debug了半天,发现这是一个非常典型且易犯的错误.记之

示例代码:

package main
import "fmt"
type aa struct {
        x, y int
}
type bb struct {
        member aa
}
func main() {
        m := []*aa{}
        pool := []bb {
                {
                        member: aa{x : 1,y : 1,},
                },
                {
                        member: aa{x : 2,y : 2,},
                },
                {
                        member: aa{x : 3,y : 3,},
                },
        }
        for _, p := range pool {
                m = append(m, &p.member)
        }
        for _, ele := range m {
                ele.x = ele.x + 1
                ele.y = ele.y + 1
        }

        for _, ele := range m {
                fmt.Printf("x=%d, y=%d\n", ele.x, ele.y)
        }
}

上面这段代码的运行结果是什么?也许你会立马答出来是:

x=2, y=2

x=3, y=3

x=4, y=4

运行一下就知道这个答案是错的.正确的运行结果是:

x=6, y=6

x=6, y=6

x=6, y=6

那么到底错在哪呢?原来在数组m中,它的三个元素是同一个指针.原来在下面这段代码中,golang是新建了一个变量p, 每次将该数组的元素

赋值给这个p,而p的地址自然是恒定的,因此最后m中的元素都是这个p的成员变量member的地址.

       for _, p := range pool {
                m = append(m, &p.member)
        }

这个例子告诉我们,在golang的数组/map迭代操作中,如果在迭代体中需要访问数组/map元素的指针,那么千万要小心了.这类bug非常难以检测.

原文地址:https://www.cnblogs.com/elnino/p/9782879.html

时间: 2024-10-09 21:17:10

golang中的那些坑之迭代器中的指针使用的相关文章

对称加密算法在C#中的踩坑日常

前言 有幸接触了一下传说中的对称加密算法3DES 感觉这些加密算法与我的工作是想去甚远的,一般没什么机会接触这些东西 今次了解了一下3DES这个对称算法 原理算不上明白,算是踩了C#中的一些坑吧 C#中对于密钥的处理比较奇怪,花费了一晚上一早上的时间才弄明白 期间偷窥了不少C#的源代码 下面由我娓娓道来 简介 3DES算法命名 定义算法最早期的标准被放在ANS X9.52中并在1998年发布并将其描述为三重数据加密算法(简称TDEA),在ANSI X3.92中定义了该算法的三个操作但是并没有使用

Netty中的那些坑

Netty中的那些坑(上篇) 最近开发了一个纯异步的redis客户端,算是比较深入的使用了一把netty.在使用过程中一边优化,一边解决各种坑.儿这些坑大部分基本上是Netty4对Netty3的改进部分引起的. 注:这里说的坑不是说netty不好,只是如果这些地方不注意,或者不去看netty的代码,就有可能掉进去了. 坑1: Netty 4的线程模型转变 在Netty 3的时候,upstream是在IO线程里执行的,而downstream是在业务线程里执行的.比如netty从网络读取一个包传递给

iOS内购(IAP)中的那些坑

公司的公共库原来并没有这部分的代码,以前做内购是用两个比较有名的github上的第三方库.一个叫MKStoreKit,另一个叫IAPManager,我看了一下写的都很辣鸡,使用起来很不方便,而且写的还不对...... 于是我自己写了一个,一开始写的也不是很好,受了上面两个垃圾库的影响(这两个库接口是用postNotification的),使用时还要监听事件,下面的小弟吐槽说不太好用.于是我又重做了一个接口为block的版本,感觉写的还是不错的.这下用的就很舒服了! 虽然github上也有几个写的

记一次Nancy 框架中遇到的坑

记一次Nancy 框架中遇到的坑 前几天,公司一个项目运行很久的Nancy框架的网站,遇到了一个很诡异的问题.Session 对象跳转到另外一个页面的时候,session对象被清空了,导致用户登录不上.搞了两天,终于解决了.于是把它记录下来,以避免其他人也碰到这种情况. 起因 公司一个Nancy 框架 开发的web网站,以前一直都是好的,nancy 框架也用在了很多项目里面,基本上已经很成熟很稳定了,但是在前几天发布某个web网站的时候,竟然出现部分用户登录不上的情况.刚开始以为是人员的权限有问

Python数组创建中的这些坑,你造吗?

本文和大家分享的主要是python 中创建数组过程中的一些坑,一起来看看吧,希望对大家 学习python 有所帮助. 1.问题的引出 在做leetcode 的题目时,遇到了一个求数组中出现次数最多的 k 个元素的题,参照答案的思路,首先利用一个 dict 记录所有元素出现的次数, key:value 中的 key 表示元素, value 表示元素出现的次数,随后根据元素出现的次数将元素放入对应的桶中,桶是一个二维数组,桶中第一个元素保存出现次数为 0 的元素,桶中第二个元素保存出现次数为 1 的

Python在迭代器中删除列表元素

在迭代器中删除列表元素是非常危险的,因为迭代器是直接对列表的数据进行引用 把列表拷贝给迭代器,然后对原列表进行删除操作就没问题了 pos=turtle.move() for each_fish in fish[:]: if each_fish.move()==pos: #鱼儿被吃掉 turtle.eat() fish.remove(each_fish) print('有一条鱼被吃') Python的List的底层是实现是一个PyObject*数组.如果每次增加一个元素都扩张内存的话效率太低,在增

探讨迭代器中为什么不能通过集合的方式删元素而是使用迭代器中的remove()方法经行删除

由该链接引发的思考:http://bbs.itheima.com/forum.php?mod=viewthread&tid=26270&mobile=1 看到这篇文章后,一副似懂非懂的样子,果断将楼主的代码拷贝到eclipse中运行了下,果断发现了些问题. 经过测试,发现总是在当集合中倒数第二个满足条件时程序才可以正常运行,否则,就会抛出ConcurrentModificationException异常 然后,我在while{it.hasNext()){和String str = (Str

jquery 的 each 方法中 return 的坑

jquery 的 each 方法中 return 的坑 Chapter 0 在项目中使用 jquery 的 each 方法时想在 each 的循环中返回一个布尔类型的值于是掉进一个坑中... Chapter 1 最初的代码: 这里的代码,虽然return 了,但是并未实际 return 值作为方法的返回值,而且还是继续往后执行. 在网上查询之后发现在 jquery 的 each 方法中如果 return true 相当于是 continue,而 return false 相当于是 break.

友盟社交分享中的那些坑

友盟社交分享中的那些坑 目前在做的产品,新版本需要支持社交分享,其实旧版本已经有了,但是被屏蔽了,本来再次打开也没什么,但是发现新的需求要多支持一个平台,而旧平台的sdk又太旧了(接口都改了),为了节约时间,就考虑友盟社交分享,文档说快速集成只要10分钟. 下面呢,咱来说下具体使用友盟分享遇到的一些问题 首先是 产品需求 为了避免大伙看大段的需求文档,咱精简出和本文相关的需求 分享到微信好友 分享到微信朋友圈 分享到qq空间 分享到新浪微博 分享图片+文字 分享视频+文字 分享纯文字 点击分享出