• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    golang中for range的取地址操作陷阱介绍

    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是一个独立对象,这个对象指向了数组中的对应元素。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

    您可能感兴趣的文章:
    • 基于golang中container/list包的用法说明
    • Golang中List的实现方法示例详解
    • golang使用grpc+go-kit模拟oauth认证的操作
    • golang如何去除多余空白字符(含制表符)
    • 用golang如何替换某个文件中的字符串
    • golang正则之命名分组方式
    • 解决golang中container/list包中的坑
    上一篇:golang如何去除多余空白字符(含制表符)
    下一篇:go实现for range迭代时修改值的操作
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    golang中for range的取地址操作陷阱介绍 golang,中,for,range,的,取,地址,