Closures
Functions that capture variables from their surrounding scope, including closures used by goroutines.
A closure is a function that uses a variable from the scope where it was created. It keeps access to that variable after the outer function returns.
Each call to this factory creates a counter with its own captured value:
package main
import "fmt"
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
counter := makeCounter()
fmt.Println(counter(), counter()) // 1 2
}A goroutine can receive the loop value as an argument. This makes a copy at the call site. All three values print, but their order may vary:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
fmt.Println(n)
}(i)
}
wg.Wait()
}In production
The module's go directive controls loop-variable semantics. Modules declaring Go 1.22 or later get a new variable for each iteration; modules declaring an older version reuse the loop variable. Passing it as an argument works in both cases.
Enjoyed this? Get more software craft delivered to your inbox.