【问题标题】:Accessing objects in a map pointer in golang, does the dereferencing causes a copy of the map? [closed]在golang中访问映射指针中的对象,取消引用会导致映射副本吗? [关闭]
【发布时间】:2021-03-15 17:49:45
【问题描述】:

在我的代码中,我创建了一个映射指针,然后我取消引用以检索项目。

a := "...big JSON string..."
b := map[string]B{}
json.Unmarshal(a, &b)
c.my_map = &b
...

// and my fetch function does:
result = (*c.my_map)[id]

当取消引用该映射指针时,它是否会在内存中创建映射的临时副本?

即当我这样做时:

d := *c.my_map

我知道我在d 中获得了地图的副本(不是深层副本,但地图本身是重复的),所以我认为上面的语句最终可能会复制所有内容......


为什么是指针?

地图由 go 例程加载,然后我将最终指针保存在我的结构中。该保存发生在锁上。加载可能很长(数据 Gb),所以这就是为什么......(现在阅读 Zuko 的答案)看起来根本不需要它,因为无论如何都会将地图作为参考传递。

【问题讨论】:

  • “解除引用”与地图值的正常读取或分配没有什么不同。它不会创建地图的深层副本。
  • 如果声明为var i *int*i 是否创建副本?如果不是,为什么地图会发生这种情况?
  • @AlexisWilke,我不明白你在问什么。是的,如果它只是被读取,那么可能没有任何副本(从技术上讲,这是一个您无法控制的实现细节),并且分配总是一个副本。但是,地图值是一个单词,因此在实践中确实没有区别。 (这也导致了为什么你首先想要一个指向地图的指针的问题?)
  • 不,没有副本。不用担心。 Go 不是 C++。
  • 您还没有回答最重要的问题:为什么您首先需要指向地图的指针?

标签: dictionary go pointers dereference


【解决方案1】:

go 中的映射很像切片是引用类型。这实质上意味着当您将引用分配给新变量或将映射传递给函数时,会复制对映射的引用。

举个例子。

 users := map[string]int{
    "1": 1, "2": 2,
 }

 userRef := &users // creates new reference to map reference
 userRef3 := *userRef // returns map reference stored in userRef3 


 // making changes to userRef3 will affect the underlying type
 userRef3["1"] = 101 // now all 3 variables have the same new value

 fmt.Println(users["1"]) //prints 101

所以基本上你不需要使用带有引用类型的指针,如映射、切片和原始指针。但如果你这样做了,Go 将简单地复制引用类型的地址,对其所做的更改将直接影响底层映射。

【讨论】:

  • 虽然我知道您可能想要近似以简化,但需要参考作者的一两个词。 dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-godave.cheney.net/2017/04/30/… In the very early days what we call maps now were written as pointers, so you wrote *map[int]int. We moved away from that when we realized that no one ever wrote `map` without writing `*map`.
  • 感谢@mh-cbon 指出这一点。非常感谢。
  • 完美!我测试了你的样本,它确实打印了 101。所以它确实只是一个传递的指针。很有趣。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 1970-01-01
  • 2020-06-27
  • 2017-05-13
  • 2014-02-20
相关资源
最近更新 更多