Yesterday’s spec quote included a sentence we breezed over. Today we’re going to dig in a bit more:
Order of Evaluation
… the order of those events compared to the evaluation and indexing of
x
and the evaluation ofy
andz
is not specified, except as required lexically.
What exactly does that mean?
Well, the example that follows in the spec makes it a bit more clear, but in a nutshell, the order of evaluation for index expressions is not defined.
Here’s the example:
a := 1 f := func() int { a++; return a } x := []int{a, f()} // x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified m := map[int]int{a: 1, a: 2} // m may be {2: 1} or {2: 2}: evaluation order between the two map assignments is not specified n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}: evaluation order between the key and the value is not specified
In other words, any time you have an index expression, the order of evaluation of the keys and values is effecively random. To prove it, run this code:
var i int
index := func() int {
i++
return i
}
s := []int{index(), index(), index(), index(), index()}
fmt.Println(s)
And you will see that it consistently outputs [1 2 3 4 5]
.
Wait. What? It consistently outputs the same thing?
Okay. So it’s not effectively random. Rather, it’s undefined.
Sound like splitting hairs?
It just means that the order may vary. When? Well, across different Go versions or implementations, or possibly even on different hardware.
If you run this code, and get a result different than [1 2 3 4 5]
, would you let me know? I’d love to know which platform/version you’re using.
Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)