【问题标题】:Does loading a map element in Go imply copying?在 Go 中加载地图元素是否意味着复制?
【发布时间】:2021-08-10 11:44:30
【问题描述】:

假设有这样的代码sn-p。

mapper := make(map[int]SomeStructType)
mapper[0] = SomeStructType{}

somestruct := mapper[0]   // load mapper[0] to 'somestruct'

在最后一行,这是否意味着mapper[0] 在所有情况下都被复制到somestruct,即使somestruct 之后曾被用作只读常量?

如果是这样,有没有办法像在 C/C++ 中一样对地图元素(此处为 mapper[0])进行 引用,以便我可以通过别名引用它,同时避免不必要的对象复制?我试图创建一个指向地图元素的指针,但显然,Go 不允许我这样做。

【问题讨论】:

  • Go 中的地图值是不可可寻址的。建议将int 映射到指向结构的指针
  • 好的,我试图避免使用指针类型的元素,因为我想以 JSON 格式导出地图,但似乎指针类型的元素也可以导出为 JSON 格式。 stackoverflow.com/questions/55813574/…
  • 但是这个问题还是有一些观点的,比如我们不能在不强制 Go 进行复制的情况下为地图元素创建别名吗?
  • @GwangmuLee 不。地图元素可以重新分配,使指针无效。所以根本不允许。
  • “这是否意味着 mapper[0] 在所有情况下都被复制到 somestruct” Go 中的 每个 赋值都是一个副本。 “即使 somestruct 之后曾经用作只读常量”也没有这样的事情。 Go 的唯一常量是编译时常量。

标签: go


【解决方案1】:

简单的答案是。在 Go 中,地图实现可能会移动数据,因此引用会失效并且不安全。在 C 中,您可以定义自己的数据结构,因此由您决定如何完成;在 Go 中,地图是在 Go 运行时中实现的,它无法猜测您的意图。

我认为,您正在寻找的解决方案是将指针保留在地图中,即:

mapper := make(map[int]*SomeStructType)

现在访问mapper 元素只会“复制”一个指针(通常是一个单词),这非常便宜。

somestruct := mapper[0] // copies a pointer

在 Go 中使用指针类型很常见,因此通过像这样定义 mapper 不会做任何太神奇或不寻常的事情。

【讨论】:

  • 虽然语义上somestruct 确实是一个副本,但编译器可以(至少理论上)在某些情况下将其优化为引用——例如,使用common-subexpression elimination 优化(如果它可以证明地图暂时不会修改)。
  • 请参阅golang.org/issue/17133,了解有关目前优化和未优化的更多细节。
猜你喜欢
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 2015-01-19
  • 2018-07-12
  • 2014-08-15
  • 1970-01-01
相关资源
最近更新 更多