使用范围时,GO迭代地图条目的顺序是否总是相同?

时间:2018-10-28 23:01:00

标签: dictionary go range

此代码将始终显示相同的结果吗? 潜在的问题:range总是会以相同的顺序迭代地图吗?

m := map[string]int {
    "a": 1,
    "b": 2,
    "c": 3,
    "d": 4,
    "e": 5,
    "f": 6,
}
for k, v := range m {
    fmt.Printf("%v = %v", k, v)
}

2 个答案:

答案 0 :(得分:7)

不,它是有意随机化的(以防止程序员依赖它,因为语言规范中未指定它)。

来自the Go Blog

  

迭代顺序

     

在具有范围循环的地图上进行迭代时,未指定迭代顺序,并且不能保证每次迭代之间都相同。从Go 1.0发布以来,运行时具有随机化的地图迭代顺序。程序员已经开始依赖Go早期版本的稳定迭代顺序,该顺序在实现之间会有所不同,从而导致可移植性错误。

答案 1 :(得分:2)

答案是:不,不是

我写了以下测试来证明这一点。

func Test_GO_Map_Range(t *testing.T) {
    originalMap := map[string]int {
        "a": 1,
        "b": 2,
        "c": 3,
        "d": 4,
        "e": 5,
        "f": 6,
    }
    getKeys := func(m map[string]int) []string{
        mapKeys := make([]string, len(m))
        i := 0
        for n := range m {
            mapKeys[i] = n
            i++
        }
        return mapKeys
    }
    keys := getKeys(originalMap)
    for i := 0; i < 5; i++ {
        assert.Equal(t, keys, getKeys(originalMap))
    }
}

我得到如下结果:

Error:          Not equal: 
                expected: []string{"d", "e", "f", "a", "b", "c"}
                actual  : []string{"a", "b", "c", "d", "e", "f"}

Error:          Not equal: 
                expected: []string{"d", "e", "f", "a", "b", "c"}
                actual  : []string{"f", "a", "b", "c", "d", "e"}

Error:          Not equal: 
                expected: []string{"d", "e", "f", "a", "b", "c"}
                actual  : []string{"c", "d", "e", "f", "a", "b"}

Error:          Not equal: 
                expected: []string{"d", "e", "f", "a", "b", "c"}
                actual  : []string{"b", "c", "d", "e", "f", "a"}

Error:          Not equal: 
                expected: []string{"d", "e", "f", "a", "b", "c"}
                actual  : []string{"a", "b", "c", "d", "e", "f"}