在Golang中,为什么地图迭代是随机的?

You*_*ung 3 dictionary go

从Golang 源代码看,它们似乎遵循哈希表(即存储桶数组)的相当标准的实现。基于此,对于不变的映射,迭代应该是确定性的(即按顺序迭代数组,然后按顺序在存储桶中迭代)。他们为什么要使迭代是随机的?

icz*_*cza 8

TL; DR; 他们故意从Go 1开始将其随机化,以使开发人员不再依赖它(不依赖特定的迭代顺序,该顺序可能会从发行到发行,从平台到平台改变,甚至可能在单个发布期间改变。由于容纳更多元素而导致地图内部变化时,应用的运行时)。

Go博客:Go行动地图:迭代顺序:

当使用范围循环在地图上进行迭代时,未指定迭代顺序,并且不能保证每次迭代之间都相同。从Go 1.0发布以来,运行时具有随机化的地图迭代顺序。程序员已经开始依赖Go早期版本的稳定迭代顺序,该顺序在实现之间会有所不同,从而导致可移植性错误。如果需要稳定的迭代顺序,则必须维护一个指定该顺序的单独的数据结构。

另请参阅1版本发行说明:在地图中进行迭代:

旧的语言规范没有定义地图的迭代顺序,实际上,它在各个硬件平台上都不同。这导致对地图进行迭代的测试是脆弱且不可移植的,具有令人不愉快的特性,即测试可能始终在一台计算机上通过而在另一台计算机上中断。

在Go 1中,即使使用同一映射多次运行同一循环,使用for range语句遍历一个映射时访问元素的顺序也被定义为不可预测。代码不应假定以任何特定顺序访问元素。

This change means that code that depends on iteration order is very likely to break early and be fixed long before it becomes a problem. Just as important, it allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map.

  • @Dippo 他们故意将其随机化,这样开发人员就不会编写依赖于特定顺序的代码。例如,如果您向映射添加三个键并且迭代顺序_发生_为“1”、“2”、“3”,则您可以编写一个_期望_此顺序的测试,并且该测试可能总是成功。然后,在下一个 Go 版本中,它可能会无缘无故地失败(如果新的或更改的映射实现会以不同的顺序迭代)... (2认同)

Eli*_*sky 4

除其他事项外,这对于安全性非常重要。

网上有很多资源讨论这个问题——例如,请参阅这篇文章