In Go, anonymous functions (func literals) are capable of creating closures, meaning they can access variables from the surrounding scope even after it has completed. Such closures allocate memory on the heap if necessary for proper functionality (detected via escape analysis).
Example:
func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum } } a := adder() printf("%d\n", a(5)) // 5 printf("%d\n", a(10)) // 15
Features:
What will this code output?
func main() { fs := []func(){} for i := 0; i < 3; i++ { fs = append(fs, func() { fmt.Println(i) }) } for _, f := range fs { f() } }
Many would answer that it will output 0, 1, 2; however, the result will be:
3
3
3
All closures refer to the same variable i; after the loop finishes, its value is 3.
Correct Approaches: Capture a copy of the variable within the loop:
for i := 0; i < 3; i++ { v := i // new variable fs = append(fs, func() { fmt.Println(v) }) }
Story
In a dynamic routing project, a loop was used to create multiple handlers via closures, each intended to capture its path. As a result, all handlers printed the last path — a separate variable was not created in each closure. The error was discovered only during integration with the HTTP API.
Story
When testing concurrent access via goroutines within a loop, the closure captured a reference to the index, not a copy. This created "random" effects: data was written not to its own array slot, but to the last one.
Story
In a statistics collection function, the closure modified a global variable from the outer scope, whereas the author expected an independent counter for each task. The problem was noticed due to an inadequately reconstructed sum, which was always global, not local, despite the local logic.