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 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.