golang使用指针修改数据引起的血案

tonnyzhang · · 369 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

背影知识:

golang 中的struct和slice为值赋值, map为引用赋值;range语句for k, v := range val 这里的v只申明了一次,每次迭代只会更新值

我们在平时应该会经常用到用指针把修改复杂对象(struct、slice、map)属性的需求,今天小编就把踩过的一个小坑跟大家分享下:

先上下代码:

package main

import (
    "fmt"
)

// Node node
type Node struct {
    Val int
}

var nodes []Node

func initData() {
    for i := 0; i < 10; i++ {
        nodes = append(nodes, Node{
            Val: i,
        })
    }

    nodes[9].Val = 100
}
func main() {

    initData()

    var mapNodes map[int][]*Node = make(map[int][]*Node, 0)

    for _, v := range nodes {
        if _, ok := mapNodes[v.Val]; !ok {
            mapNodes[v.Val] = make([]*Node, 0)
        }
        mapNodes[v.Val] = append(mapNodes[v.Val], &v)
    }

    node := mapNodes[0][0]
    node.Val = 200

    fmt.Println(nodes)
}

输出

[{0} {1} {2} {3} {4} {5} {6} {7} {8} {100}]

期望输出

[{200} {1} {2} {3} {4} {5} {6} {7} {8} {100}]

可以明显看出我们更改的第一个元素的值没有生效,第一个原因是range造成的问题,我们不能直接使用&v去作为指向原始元素的地址,此时想得到原始元素的地址,必须明确找到元素,可以使用以下方案:

    for i, v := range nodes {
        if _, ok := mapNodes[v.Val]; !ok {
            mapNodes[v.Val] = make([]*Node, 0)
        }
        mapNodes[v.Val] = append(mapNodes[v.Val], &(nodes[i]))
    }

修改完成后,再看下输出即是我们想要的结果

[{200} {1} {2} {3} {4} {5} {6} {7} {8} {100}]

其实range语句里的v即为一个赋值操作,等价于v := nodes[i],此时的赋值操作v已经是一个新的地址和原始数据nodes[i]已经不是同一个地址,故后续想通过&v是找不到原始数据的


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:tonnyzhang

查看原文:golang使用指针修改数据引起的血案

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

369 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传