【问题标题】:Golang behaviour on map definition with static content (compile time construction?)具有静态内容的地图定义上的 Golang 行为(编译时构造?)
【发布时间】:2021-12-25 01:38:36
【问题描述】:

让我们采用以下 Golang 表达式:

type MyStruct struct {
  foo int,
  bar map[string]MyInterface 
}
type MyInterface interface { /* ... */ }
func firstFunc() { /* ...*/ }
func secondFunc() { /* ...*/ }

具有以下构建器功能:

func NewMyStruct() *MyStruct {
  // Building a map made of only static content, known at compile time
  // Assigning it to a local variable
  m := map[string]MyInterface {
    "first": firstFunc,
    "second": secondFunc,
  }
  /* ... */
  return &MyStruct{
    bar: m, // Copying the map into the struct field
    /* ... */
  }
}

我遇到了这段代码,并决定尝试在内存管理和/或执行时间方面对其进行优化。 来自 C++ 世界,我习惯了“静态分配与动态分配”的困境以及constexpr 的使用。我试图在 Golang 中实现相同的目标:避免在语言允许的范围内过于频繁地构造/分配数据结构。

问题 1:在 NewMyStruct() 中,分配给 m 的临时映射是否有效在每次调用时构造/分配?

问题2:编译器能否检测到临时地图是由静态内容构成的,一次性构造出来?

我的另一个解决方案是使用全局定义的映射并使用指针从 MyStruct 实例中引用它。

【问题讨论】:

  • Q1:是的。地图是可变的,而不是静态的。 Q2:没有。理论上它可能在某些版本的 Go 的某些编译器中,但当前标准的 go 编译器没有。
  • 最后一句话——很少需要指向map 的指针,因为map 已经是指向底层数据结构的指针。
  • 那么......我可以做些什么来改进这段代码?如果是指向底层结构的指针,如何保证浅拷贝(考虑享元模式)?
  • 这是过早的优化。
  • @Volker 也许在 Go 中。从 C++ 的角度来看,它只是通过利用语言的效率来做正确的事情......

标签: go memory-management


【解决方案1】:

作为Volker suggests,这几乎可以肯定是过早的优化。但是,如果您已经发现这会在您的程序中花费大量时间并且只是在寻找选项,this Playground link 会显示一种在程序启动时构建地图并共享它的方法。本质就是:

return &MyStruct{bar: sharedMap, /*...*/}

此时需要创建共享地图。如果无法进行简单的静态初始化,请使用an init function,或添加sync.Once,以便在第一次调用New 函数时仅构造一次映射。

【讨论】:

  • 我知道这是过早的优化,实际上我并没有要求优化这段代码。相反,我想知道语言/编译器是否提供了我不知道的用于编写高效代码的甜蜜功能(寻找最佳实践)。正如我所说,在 C++ 中,我很容易避免在每次调用时构建临时对象,并且我正在尝试在这个主题上学习 Go。
猜你喜欢
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多