Mohammed Manssour

The Quirky Go Loop: A Bug Fixed in Go 1.22

Go

Talking with other developers is always fun. I love telling them why Go is a great language. I tell them it's fast but also has tools like garbage collection. But they always bring up the same thing: the weird loop bug.

"You have to use a workaround!" they say.

I tell them all languages have bugs. But Go 1.22 fixed this one. They'll have to find a new complaint for next time!

The Go Loop Bug

Many developers have faced this problem. You write a for loop, but the code does something you don't expect.

Look at this example:

func main() {
    values := []string{"A", "B", "C"}
    var fns []func()
    
    for _, v := range values {
        fns = append(fns, func() {
            fmt.Println(v)
        })
    }
    
    for _, fn := range fns {
        fn()
    }
}

In older versions of Go, this code would print "C" three times. This happened because the loop's variable, v, was only created once. All the functions used the same v. By the time the functions ran, v was already "C".

The Old Fix

Before Go 1.22, you had to add an extra line of code to fix this. You had to create a new variable inside the loop. This gave each function its own variable to use.

The fix looked like this:

for _, v := range values {
    v_ := v // This line fixed it
    fns = append(fns, func() {
        fmt.Println(v_)
    })
}

Go 1.22 Solves It

Go 1.22 fixes the problem for good. The loop now creates a new variable for each turn. You no longer need the extra line of code. The first code example will now work as you'd expect and print "A", "B", and "C".

This change makes Go code simpler and easier to read. It's a great improvement for all Go developers.

Crafted with love by Mohammed Manssour