For statements with
range
clause…
Function calls on the left are evaluated once per iteration.
This small sentence is easy to overlook. What does it mean?
It means if you have any function calls on the left hand side of the for range statement, they are executed per iteration. What would that even look like? It’s probably a rare occurrence, but here’s an example in the playground:
func main() {
for _, m()["foo"] = range []string{"foo", "bar", "baz"} {
}
fmt.Println(globalMap)
}
var globalMap = make(map[string]string)
func m() map[string]string {
fmt.Println("m() called")
return globalMap
}
Notice the call to m()
in the left-hand side of the for-range statement. The function m()
returns a map, which is in turn dereferenced to receive the range assignment.
But this code also proves that m()
is called for each iteration of the loop, as it outputs:
m() called
m() called
m() called
map[foo:baz]
indicating three calls to m()
, before showing the final output of the map returned by m()
.
Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)