为什么Golang不允许const映射?

时间:2016-06-23 06:58:01

标签: dictionary go

我想创建一个如下所示的常量映射:

const (
    running = map[string]string{
        "one": "ONE",
        "two": "TWO",
    }
)

然而每当我这样做时,我都会收到以下错误:

const initializer map[string]string literal is not a constant

为什么会出现这种情况,为什么Golang不像其他任何变量一样对待它们?

2 个答案:

答案 0 :(得分:16)

来自https://golang.org/ref/spec#Constants

  

常量值由符文,整数,浮点数表示,   imaginary,或string literal,表示常量的标识符,a   常量表达式,具有常量结果的转换,或   一些内置函数的结果值,如unsafe.Sizeof   适用于某些表达式的任何值,上限或len,真实和   imag应用于复数常量和复数应用于数值   常数。

tl; dr只有数字类型,字符串和bool可以是常量,数组,切片和地图不是数字类型。

答案 1 :(得分:2)

我对此的看法是,这个决定纯粹是务实的:Go是一种非常脚踏实地的语言(与其他语言相反 - “更纯粹的” - 语言),以及一些真实世界地图实现的一个有趣属性只是访问它们进行阅读可能会更新其内部表示(!)。比如,他们可能会收集并存储一些关于其使用情况的统计信息,或者他们可能会重新平衡保存值桶的基础树等。允许存在“const map”意味着在语言规范中明确指定一组复杂约束 - 大多数可能要求实现有两个地图实现。

你也可以尝试从另一个角度来看它:考虑一个字符串常量。这样的东西可能很容易嵌入到生成的二进制文件的.rodata部分中,并且实际上由内存中的数据地址表示(好吧,Go中的字符串更复杂,但让我们忽略该细节)。也就是说,一个常量字符串可以是真正的“静态”:它只是内存中的一系列静态R / O字节 - 就这么简单。 相反,地图是一个由复杂机械驱动的高度复杂的野兽,每个地图都是一个特殊的复杂对象在运行时实例化。这就是为什么你甚至不能只声明地图并使用它:你必须{ {1}}它首先 - 就像频道一样,出于同样的原因。

同样,可能会做一些黑客来支持常量地图。 比如说,实现可以预先对地图的键进行排序,将其(带有值)序列化为R / O数据的连续区域,然后在运行时使用二进制搜索来查找值。对于大型地图/某些关键模式而言,这可能是无效的,但据说可行。 尽管如此,这将是一个完全不同于“普通”的专业地图实现。我认为Go开发人员认为这种权衡不值得利益。

两个后续注释:

  • 如您所见,您可以相对轻松地模拟只读地图: 有一些切片文字的一些结构类型嵌入键和值, 在键上预先排序,并将其包装在执行二进制的函数中 搜索密钥。

  • 我更倾向于认为Go的常量有点像C中的宏 语言:它们是无类型的,感觉就像文本一样(它们不是 但我毕竟说的是感觉;) - )

    请务必阅读this以获得精彩概述。