Iteration over maps

June 19, 2024

For statements with range clause

  1. 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.

The idea that map porder is non-deterministic in Go is simple, but often forgotten or overlooked. It has three distinct implications, which are spelled out. Let’s go through each one:

  • When ordering over the same map multiple times, you may get a different order of results.

    for k, v := range map[string]string{"cow": "moo", "pig": "oink"} {
    	fmt.Println(k, v)
    }
    

    may produce:

    cow moo
    pig oink
    

    or

    pig oink
    cow moo
    
  • Keys deleted while ranging won’t be visited

    … however this can result in some non-deterministic behavior in some cases. Consider:

    m := map[string]string{"cow": "moo", "pig": "oink"}
    for k, v := range m {
    	fmt.Println(k, v)
    	delete(m, "cow")
    }
    

    After running this code, m will always equal map[string]string{"pig": "oink"}, but depending on the order of the iteration, the output may be either

    cow moo
    pig oink
    

    or

    pig oink
    
  • Keys inserted into a map while ranging, may or may not be visited during iteration.

    m := map[string]string{"cow": "moo"}
    for k, v := range m {
    	fmt.Println(k, v)
    	m["chicken"] = "cluck"
    }
    

    will set m to equal map[string]string{"cow": "moo", "chicken": "cluck"}, but the output may be either:

    cow moo
    

    or

    cow moo
    chicken cluck
    

All this to say, it’s important to be intentional when ranging over maps. The results are unpredictable!

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe