【问题标题】:Why doesn't Golang allow const maps?为什么 Golang 不允许 const 映射?
【发布时间】:2016-10-25 08:34:00
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 我认为为什么这个问题的答案是,go 的作者认为实现的复杂性不值得它带来的好处。
  • declare a constant array的可能重复
  • 我认为您可能想要一个不可变的地图。你不能仅仅因为 Go 语言中的 map 是一种语言结构而不是某些Map 接口的实现而声明不可变映射。也就是说,您无法实现自己的地图(通过接口)与内部 Go 地图兼容。

标签: dictionary go


【解决方案1】:

我对此的看法是,这个决定纯粹是务实的:Go 是一种非常实用的语言(与其他“更纯粹”的语言相反),并且是一些现实世界地图实现的一个有趣属性仅仅是为了阅读而访问它们可能会更新它们的内部表示(!)。比如说,他们可能会收集并存储一些关于其使用情况的统计数据,或者他们可能会重新平衡保存值桶等的底层树。允许“const map”存在意味着在语言规范中明确指定一组复杂的约束— 很可能需要实现有两个地图实现。

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

同样,可以做一些修改来支持常量映射。 比如说,一个实现可以预先对映射的键进行排序,将其(使用值)序列化为 R/O 数据的连续区域,然后在运行时使用二进制搜索来查找值。对于大型地图/某些关键模式,这将是非常无效的,但据说会起作用。 尽管如此,那将是一种与“正常”完全不同的专业地图实现。我认为 Go 开发者认为这种权衡不值得可能的好处。

两个后续说明:

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

  • 我更喜欢将 Go 的常量视为类似于 C 语言中的宏 语言:它们是无类型的,感觉像文本(它们不是 但我毕竟是在谈论感觉);-)

    请务必阅读 this 以了解详细信息。

【讨论】:

    【解决方案2】:

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

    常量值用符文、整数、浮点数表示, 虚构的或字符串文字,表示常量的标识符,a 常量表达式,结果为常量的转换,或 unsafe.Sizeof 等一些内置函数的结果值 应用于任何值,cap 或 len 应用于某些表达式,real 和 图像应用于复数常数和复数应用于数值 常量。

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

    【讨论】:

    • 另外,函数不能声明为常量。
    猜你喜欢
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    相关资源
    最近更新 更多