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

但是,无论何时我都会收到以下错误:

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

为什么会这样,为什么Golang不会像对待其他变量一样对待它们?

从https://golang.org/ref/spec#Constants:

A constant value is represented by a rune, integer, floating-point,
imaginary, or string literal, an identifier denoting a constant, a
constant expression, a conversion with a result that is a constant, or
the result value of some built-in functions such as unsafe.Sizeof
applied to any value, cap or len applied to some expressions, real and
imag applied to a complex constant and complex applied to numeric
constants.

tl; dr仅数字类型,字符串和布尔值可以是常量,数组,切片和映射不是数字类型。

我对此的看法是,这个决定纯粹是务实的:Go是一种非常扎实的语言(与其他"更纯粹的"语言相对),并且某些现实世界地图实现的一个有趣特性是仅访问它们阅读可能会更新其内部表示(!)。说,他们可能会收集并存储有关其用法的统计信息,或者可能会重新平衡保存值桶等的基础树。允许存在" const map"意味着在语言规范中明确为其指定一组复杂的约束最有可能要求实现具有两个映射实现。

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

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

两个后续注意事项:

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

  • 我更喜欢考虑Go的常量有点像C语言中的宏
    语言:它们是无类型的,感觉像是文字(它们不是
    但我毕竟是在谈论感觉);-)

    请务必阅读此内容以获得很好的概述。