Go

What does this print? (Hint: consider the go line in go.mod.)

Question 420HardGo 1.22 to 1.25
// go.mod:  go 1.21
package main

import "fmt"

func main() {
    var fns []func()
    for i := 0; i < 3; i++ {
        fns = append(fns, func() { fmt.Print(i, " ") })
    }
    for _, f := range fns {
        f()
    }
}

Answer: with go 1.21 (or lower) it prints 3 3 3. Change go.mod to go 1.22 and it prints 0 1 2, even when you compile both with the same Go 1.23 toolchain.

The per-iteration loop variable semantics of Go 1.22 are gated on the language version of the module (or file) being compiled, not on the toolchain version. This kept the change backward compatible: old dependencies keep their old behavior while your module gets the new one.

You can also override the version per file with a build constraint, which sets that file's language version:

//go:build go1.22

package main

Interviewers use this to test whether you know that the go line is more than documentation. Related tooling: go vet's loopclosure check, and bisect / -gcflags=-d=loopvar=2, which helped find code that relied on the old sharing behavior when the change shipped.

More on Modules, Packages & Tooling

All 36 Modules, Packages & Tooling questions