Captured Closure (for Loop Variable) in Go

Do you want the closure over the variable or the value? For example,

package main

import "fmt"

func VariableLoop() {
    f := make([]func(), 3)
    for i := 0; i < 3; i++ {
        // closure over variable i
        f[i] = func() {
            fmt.Println(i)
        }
    }
    fmt.Println("VariableLoop")
    for _, f := range f {
        f()
    }
}

func ValueLoop() {
    f := make([]func(), 3)
    for i := 0; i < 3; i++ {
        i := i
        // closure over value of i
        f[i] = func() {
            fmt.Println(i)
        }
    }
    fmt.Println("ValueLoop")
    for _, f := range f {
        f()
    }
}

func VariableRange() {
    f := make([]func(), 3)
    for i := range f {
        // closure over variable i
        f[i] = func() {
            fmt.Println(i)
        }
    }
    fmt.Println("VariableRange")
    for _, f := range f {
        f()
    }
}

func ValueRange() {
    f := make([]func(), 3)
    for i := range f {
        i := i
        // closure over value of i
        f[i] = func() {
            fmt.Println(i)
        }
    }
    fmt.Println("ValueRange")
    for _, f := range f {
        f()
    }
}

func main() {
    VariableLoop()
    ValueLoop()
    VariableRange()
    ValueRange()
}

Output:

VariableLoop
3
3
3
ValueLoop
0
1
2
VariableRange
2
2
2
ValueRange
0
1
2

References:

The Go Programming Language Specification

Function literals

Function literals are closures: they may refer to variables defined in
a surrounding function. Those variables are then shared between the
surrounding function and the function literal, and they survive as
long as they are accessible.

Go FAQ: What happens with closures running as goroutines?

To bind the current value of v to each closure as it is launched, one
must modify the inner loop to create a new variable each iteration.
One way is to pass the variable as an argument to the closure.

Even easier is just to create a new variable, using a declaration
style that may seem odd but works fine in Go.

Leave a Comment