For statements with
for
clause…
Each iteration has its own separate declared variable (or variables) [Go 1.22].
This seemingly simple sentence carries a lot of weight. So that’s what we’ll be talking about today.
Prior to Go 1.22 (which only came out earlier this year!), the loop variable was re-used, rather than re-declared for each loop iteration. This lead to a lot of confusion and bugs. I won’t go into those details here, since, thankfully, it’s no longer a problem… usually. If you’re interested, I recommend Fixing For Loops in Go 1.22 for a description of the problem and fix.
For our purposes, you’ll only care about this if either of the following things are true:
-
You’re reading a book or tutorial that warns against this problem. You can disregard this advice, unless the following is also true:
-
You’re building a Go module that must support old versions of Go. The version found in your
go.mod
controls this behavior, even if you’ve installed Go 1.22.0 or newer. If you’re building a library that needs to maintain backward compatibility, you’ll need to consider the old looping behavior for as long as you’re supporting older versions of Go.
So what’s the TL;DR; solution if you need to support this old behavior?
Replace this:
for i := 0; i < 10; i++ {
/* do something with i */
}
with this:
for i := 0; i < 10; i++ {
i := i
/* do something with i */
}
This re-declares a scope-specific instance of i
, which is not shared between loop iterations. And this fix is also completely safe (though unnecessary) in Go 1.22.0+, so you needn’t worry about removing it later.
Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)