Golang在使用静态内容定义map时的行为(编译时构建?)

huangapple go评论148阅读模式
英文:

Golang behaviour on map definition with static content (compile time construction?)

问题

让我们来看一下以下的 Golang 表达式:

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

以及以下的构建函数:

func NewMyStruct() *MyStruct {
  // 由编译时已知的静态内容构建一个映射
  // 将其赋值给一个局部变量
  m := map[string]MyInterface {
    "first": firstFunc,
    "second": secondFunc,
  }
  /* ... */
  return &MyStruct{
    bar: m, // 将映射复制到结构体字段中
    /* ... */
  }
}

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

问题 1:在 NewMyStruct() 中,临时映射 实际上 每次调用都会被构建/分配吗?

问题 2:编译器能否检测到临时映射由静态内容构成,并为其构建一次以供所有调用使用?

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

英文:

Lets take the following Golang expressions :

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

with the following builder function :

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
    /* ... */
  }
}

I came across this code and decided to try optimizing it in terms of memory management and/or execution time.
Coming from the C++ world, I am used to the "static vs dynamic allocation" dilema and the use of constexpr. I am trying to achieve the same goal here in Golang: avoid constructing/allocating a data structure too often in the limits of what the language permits.

Question 1: In NewMyStruct(), is the temporary map effectively assigned to m constructed/allocated at each call?

Question 2: Can the compiler detect that the temporary map is made of static content, and construct it once for all?

My other solution is to go for a globally defined map and refer to it from the MyStruct instances using a pointer.

答案1

得分: 2

根据Volker的建议,这几乎可以确定是过早优化。然而,如果你已经发现在你的程序中这会带来一些显著的时间成本,并且只是在寻找选项,这个Playground链接展示了一种在程序启动时构建并共享map的方法。核心思想就是:

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

在这一点上,共享的map需要被创建。如果简单的静态初始化不可行,可以使用init函数,或者在第一次调用New函数时添加sync.Once来构建map。

英文:

As Volker suggests, this is almost certainly premature optimization. However, if you've already found that this has some significant time cost in your program and are just looking for options, this Playground link shows a way to construct a map at program startup time and share it. The essence is just:

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

The shared map needs to be created by this point. If a simple static init is not possible, use an init function, or add a sync.Once to construct the map only once on the first call to your New function.

huangapple
  • 本文由 发表于 2021年11月13日 02:17:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/69947433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定