Go 1.22’s Loop Variable Fix

110 views
Skip to first unread message

Slawomir Pryczek

unread,
Mar 10, 2026, 2:28:14 PM (2 days ago) Mar 10
to golang-nuts
Hey Guys, i have some simple golang code which i run trough claude, it claims i have "a classic goroutine closure bug as all_params is passed to goroutine by reference", but instance of this variable should be created in each loop iteration as it's defined in the loop's body, not outside. So it doesn't matter (as i understand) if that's a reference or not.

Loop Variable Capture bug was fixed in go 1.22 and it's 2 years old already, and I don't need that code to compile in some ancient golang versions. By just capturing variables everywhere instead of passing, everything's more readable. Is that considered correct / safe approach or considered bad practice?

Apart from the main topic i have impression that this AI is just hallucinating and telling me what I want to hear. Eg. when i put some code in there looking for bugs it often finds (probably non-existing) bugs. Then I claim these bugs are not there and this code should be working as expected, and it (again) completely agrees with me telling me that there is no issue :D

 You have some good (better) model for that ?

--------------------------------------------
const MAX_PARALLEL_CALLS = 10

ret := make([]string, MAX_PARALLEL_CALLS)
if data.GetParamExists("mdata-0") { // check if we're doing multi-call
wg := sync.WaitGroup{}

for i := 0; i < MAX_PARALLEL_CALLS; i++ {
pname := fmt.Sprintf("mdata-%d", i)
if !data.GetParamExists(pname) {
break
}
all_params := get_all_params(data.GetParamBUnsafe(pname, []byte{}))

wg.Add(1)
go func() {
ret[i] = this.runOpenRTB(all_params, is_debug)
wg.Done()
}()
}
wg.Wait()

Davis Goodin

unread,
Mar 10, 2026, 2:53:27 PM (2 days ago) Mar 10
to golang-nuts
I'm still seeing this sometimes with LLM reviews too. I suspect it could be fixed by adding some "modern" hints to the context in whatever way your tooling lets you do that, but it hasn't been enough of a thorn for me to try that myself. (It's rare, recently, for me.)

Yes, as far as I can tell, it's normal to capture loopvars for readable code, and it's normal to remove the now-redundant workarounds. Here's a recent (Oct 2025) commit in Go itself that removes a bunch:  all: remove unnecessary loop variable copies in tests · golang/go@b5aefe0. That also happens to show a decent number of times the loopvar is captured in Go tests!

tapi...@gmail.com

unread,
Mar 11, 2026, 4:52:09 AM (yesterday) Mar 11
to golang-nuts
Go 1.22's for-range semantic change is overall good, but 3-clause-for change creates more gotchas. See:

The gotchas will appear when go version is upgraded from 1.22- to 1.22+.
Some of them are hard to detect in time.
Go officials never has a plan to develop tools to detect such gotchas.

So, personally, I recommended you to keep the "i := i" lines in 3-clause-for loops, even in 1.22+ error.
It is best to let compiler instead of humam to remove such lines.
Reply all
Reply to author
Forward
0 new messages