What does this print before Go 1.22 and in Go 1.22+?
Question 478MediumGo 1.22 to 1.25
func main() {
var wg sync.WaitGroup
var ptrs []*int
for i := 0; i < 3; i++ {
ptrs = append(ptrs, &i)
wg.Add(1)
go func() {
defer wg.Done()
fmt.Print(i, " ")
}()
}
wg.Wait()
for _, p := range ptrs {
fmt.Print(*p, " ")
}
}
Before 1.22: the loop had one variable i shared by all iterations. The goroutines usually print 3 3 3 (it is a data race, so any of 0..3 is possible), and the pointers all point to the same variable, printing 3 3 3.
Go 1.22+: each iteration gets a fresh i. Goroutines print 0 1 2 in some order (scheduling is nondeterministic) and the pointers print 0 1 2.
Gotcha: the semantics are chosen by the go directive in go.mod, not the toolchain version. A module declaring go 1.21 built with Go 1.23 still gets the old behavior. The interviewer wants you to mention the old fix (i := i or passing i as an argument), the go.mod subtlety, and that goroutine print order is never guaranteed.
More on Tricky Output & Code-Review Puzzles
- Q479What do these two loops print when the body changes the loop variable?
- Q480What does this print, and what is the bug in the second function?
- Q481When are deferred call arguments evaluated? What prints?
- Q482What do f(), g(), and h() return?
- Q483What does this append puzzle print?
- Q484What does the caller see after calling modify?