从Golang 源代码看,它们似乎遵循哈希表(即存储桶数组)的相当标准的实现。基于此,对于不变的映射,迭代应该是确定性的(即按顺序迭代数组,然后按顺序在存储桶中迭代)。他们为什么要使迭代是随机的?
TL; DR; 他们故意从Go 1开始将其随机化,以使开发人员不再依赖它(不依赖特定的迭代顺序,该顺序可能会从发行到发行,从平台到平台改变,甚至可能在单个发布期间改变。由于容纳更多元素而导致地图内部变化时,应用的运行时)。
当使用范围循环在地图上进行迭代时,未指定迭代顺序,并且不能保证每次迭代之间都相同。从Go 1.0发布以来,运行时具有随机化的地图迭代顺序。程序员已经开始依赖Go早期版本的稳定迭代顺序,该顺序在实现之间会有所不同,从而导致可移植性错误。如果需要稳定的迭代顺序,则必须维护一个指定该顺序的单独的数据结构。
旧的语言规范没有定义地图的迭代顺序,实际上,它在各个硬件平台上都不同。这导致对地图进行迭代的测试是脆弱且不可移植的,具有令人不愉快的特性,即测试可能始终在一台计算机上通过而在另一台计算机上中断。
在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.