为什么 Go 切片不能像数组可以用作键一样在 Go 地图中用作键?



为什么不能将go slice(这是GO数组的实现)用作GO MAPS中的键,几乎可以用作键的方式?

这是https://groups.google.com/forum/# !! Topic/golang-nuts/zylx6sr4f8y:

一个原因是数组是值类型。如果a0[N]int(一个 阵列)然后做

a1 := a0
a1[0] = 0

根本不会影响 a0[0]

相比,切片是指基础数组。复制切片 值是O(1)而不是O(长度)。如果s0[]int(切片) 然后做

s1 := s0
s1[0] = 0

会影响 s0[0]是什么。

http://play.golang.org/p/tvkntislo8

地图密钥需要一些平等概念。对于数组,这简直就是 元素平等。对于切片,有多种方法 定义平等:一个是元素平等,另一个是指 同一数组备份商店。此外,图插入确实需要 制作(昂贵的)整个备用阵列的副本?复制会 可能不那么令人惊讶,但它与什么不一致 作业做。

此代码段应该打印什么?

m := make(map[[]int]bool)
s0 := []int{6, 7, 8}
s1 := []int{6, 7, 8}
s2 := s0
m[s0] = true
s2[0] = 9
println(m[s0])
println(m[s1])
println(m[s2])

不同的程序员可以有不同的期望。避免 混乱,我们只是决定不允许切片作为地图键 现在。

回答确切的"为什么不能?":

规格:地图类型:

比较运算符==和!=必须为密钥类型的操作数充分定义;因此,密钥类型不得是函数,地图或 slice

规格不允许在未定义比较的情况下进行关键类型。规格:比较操作员还确认了这一点:

slice ,地图和功能值是不可比较

有关推理,请参见Smarx的答案(引用Nigel Tao的答案)。并继续阅读。

GO的地图使用Hashmap实现。通常,(无论编程语言如何)突变被用作hashmap中键的值可能导致不确定的(或意外的最少)行为。通常,键的标签用于指定放置值(键值对)的桶。如果密钥更改并要求该密钥的关联值,则实现可能会以错误的存储键看(因此报告它找不到它),因为更改的键值很可能会产生不同的hashcode不同的桶。

在Go Slices中只是对基础数组连续部分的描述符,而分配切片值仅复制这些描述符。因此,使用切片作为钥匙,您会期望地图实现仅复制此切片标头(这是指向基础数组中第一个引用元素的指针,长度和容量)。它只有在哈希(Hash Comptation)和平等性使用这3个元素时才起作用,而其他任何内容都没有,但对我们(人类,程序员)来说,切片意味着可以通过slice标头访问的元素 - 也可以修改(引起上面描述的问题)。

如果映射允许切片作为密钥,则可以正常运行,只要修改任何切片的切片(用作键),它就必须更新其内部状态和数据结构预期。

数组在这方面很酷:一个数组表示其所有元素;复制阵列副本所有元素,并将比较定义为:

如果数组元素类型的值是可比的,则

数组值是可比的。如果它们的相应元素相等,则两个数组值相等。

,如果您修改了以前用作键的数组的元素:不是问题,因为新数组(带有修改的元素)不等于在地图中存储和使用的原始内容,因此请查询与修改数组的关联值将合理地产生任何结果,并且使用未修改的原始数组的查询将适当地给您以前存储的值。

相关内容

  • 没有找到相关文章