Go 1.21 will include an experimental setting to change the loop variable behavior. It solves this problem as well as similar loop problems outside goroutine context that include, in one way or another, delayed evaluation of the captured loop variable.
The setting is experimental (that is, it must be enabled manually), because the Go team is extremely cautious about language changes that might break existing Go code.
The Go team is extremely cautious about language changes that could damage existing Go code, hence the setting is experimental (i.e., it must be activated manually).
The Go team is extremely cautious about language changes that could damage existing Go code, hence the setting is experimental (i.e., it must be activated manually).
this is expected behavior, every other language with threading that can use a closure type function works this exact same way.
you either need to capture the state inside the closure. the best and least surprising way is with an argument to the function. the other way is subtle and can be missed by even people experienced with the language by just assigning a variable in the local scope to the value at the time the instance of the function is created, most of the time you see this done in the worst way possible; variable shadowing, which in your case would look like. “clever” programmers use the “shorthand” implicit version that catches newbies and even themselves out later when they are reading the code.
func() {
i := i
go fmt.Println(i)
}()
an explicit function argument is the best way to convey the semantic that is required.