为什么 Golang 不允许 const 映射?

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


const (

    running = map[string]string{

        "one": "ONE",

        "two": "TWO",

    }

)

但是,每当我这样做时,都会出现以下错误:


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


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


婷婷同学_
浏览 214回答 2
2回答

心有法竹

来自https://golang.org/ref/spec#Constants:常量值由符文、整数、浮点、虚数或字符串文字、表示常量的标识符、常量表达式、结果为常量的转换或某些内置函数的结果值表示函数,例如 unsafe.Sizeof 应用于任何值,cap 或 len 应用于某些表达式,real 和 imag 应用于复数常数,复数应用于数值常数。tl; dr 只有数字类型,字符串和布尔值可以是常量,数组,切片和映射不是数字类型。

四季花海

我对此的看法是,这个决定纯粹是务实的:Go 是一种非常实用的语言(与其他“更纯粹”的语言相反),一些现实世界地图实现的一个有趣的特性是访问它们进行阅读可能会更新它们的内部表示(!)。比如说,他们可能会收集并存储一些关于其使用情况的统计数据,或者他们可能会重新平衡保存值桶等的底层树。允许“const map”存在意味着在语言规范中明确指定一组复杂的约束— 最有可能要求实现有两个地图实现。您也可以尝试从另一个角度看待它:考虑一个字符串常量。这样的东西可能很容易嵌入到.rodata生成的二进制文件的部分中,并且实际上由该数据在内存中的地址表示(好吧,Go 中的字符串更复杂,但让我们忽略这个细节)。也就是说,一个常量字符串可以是真正的“静态”:它只是内存中的一系列静态 R/O 字节——就这么简单。相反,地图是由复杂机器驱动的高度复杂的野兽,每个地图都是在运行时实例化的特殊复杂对象。 这就是为什么你甚至不能只声明一个映射并使用它:你必须make()首先使用它——就像通道一样,并且出于同样的原因。同样,可以进行一些 hack 来支持常量映射。比如说,一个实现可以预先对映射的键进行排序,将其(使用值)序列化为 R/O 数据的连续区域,然后在运行时使用二进制搜索来查找值。对于大型地图/某些关键模式,这将是非常无效的,但据说会起作用。尽管如此,那将是一种与“正常”完全不同的专业地图实现。我认为 Go 开发者认为这种权衡不值得可能的好处。两个后续说明:如您所见,您可以相对轻松地模拟只读映射:拥有一些嵌入键和值的结构类型的切片文字,对键进行预排序,并将其包装在对键执行二进制搜索的函数中。我更喜欢认为 Go 的常量有点像类 C 语言中的宏:它们是无类型的并且感觉像是文本的(它们不是,但我毕竟是在谈论感觉);-)请务必阅读此内容以获得很好的概述。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go