Loop Variable Captured by Closure

loop variable i captured by func literal (govet)

Quick Answer

The goroutine or closure captures the loop variable by reference, so all iterations share the same variable. Create a local copy or pass it as a parameter.

Why This Happens

In Go versions before 1.22, the loop variable is a single variable reused across iterations. If a closure or goroutine captures it, all of them see the final value of the variable. This is fixed in Go 1.22+ where each iteration gets its own variable, but is still a common issue in older codebases.

The Problem

func main() {
    values := []int{1, 2, 3}
    for _, v := range values {
        go func() {
            fmt.Println(v) // prints 3, 3, 3
        }()
    }
    time.Sleep(time.Second)
}

The Fix

func main() {
    values := []int{1, 2, 3}
    for _, v := range values {
        v := v // create new variable for each iteration
        go func() {
            fmt.Println(v) // prints 1, 2, 3
        }()
    }
    time.Sleep(time.Second)
}

Step-by-Step Fix

  1. 1

    Identify the captured variable

    Find closures or goroutines inside loops that reference the loop variable.

  2. 2

    Create a local copy

    Add v := v at the start of the loop body to create a new variable per iteration.

  3. 3

    Or pass as parameter

    Alternatively, pass the variable as a function argument: go func(v int) { ... }(v).

Bugsly catches this automatically

Bugsly's AI analyzes this error pattern in real-time, explains what went wrong in plain English, and suggests the exact fix — before your users even report it.

Try Bugsly free