zoukankan      html  css  js  c++  java
  • 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
    ", 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非常难以检测.

  • 相关阅读:
    贝塞尔曲线应用(贝塞尔插值)
    贝塞尔曲线原理(简单阐述)
    STL头文件有哪些及简单介绍
    句柄与MFC对象关系和相互获取
    Reflect
    Set 和 Map 数据结构
    Symbol
    对象的新增方法
    对象的扩展
    数组的扩展
  • 原文地址:https://www.cnblogs.com/elnino/p/9782879.html
Copyright © 2011-2022 走看看