dictionarygo

Modifying map while iterating over it in Go


Given the following code I would expected an infinite loop but the loop is being stopped at certain point.

m := make(map[int]string, 4)
m[0] = "Foo"
    
for k, v := range m {
    m[k+1] = v
}

I cannot figure out what happen under the hood because different execution return different output. For example these are a few outputs from different executions:

map[0:Foo 1:Foo 2:Foo 3:Foo 4:Foo 5:Foo 6:Foo 7:Foo]
map[0:Foo 1:Foo]
map[0:Foo 1:Foo 2:Foo]

How range works in order to exit from loop at certain point and what is the exit condition?


Solution

  • Spec: For statements with range clause says the behavior is unpredictable:

    The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. If a map entry that has not yet been reached is removed during iteration, the corresponding iteration value will not be produced. If a map entry is created during iteration, that entry may be produced during the iteration or may be skipped. The choice may vary for each entry created and from one iteration to the next. If the map is nil, the number of iterations is 0.

    Adding elements to the map you're ranging over, those entries may or may not be visited by the loop, you should not assume anything regarding to that.