In Go, anonymous functions (function literals, closures) were introduced to support functional style, callbacks, and concise encapsulation of algorithms. They are often used for processing collections, asynchronous tasks, and passing as parameters.
Without anonymous functions, the code becomes verbose: each processing task has to be extracted into a separate named function. However, they raise questions: how does variable "capture" work, where is the memory stored, what are the nuances when declaring and passing them as arguments? Is the variable capture safe if they are modified externally? A common error is incorrect variable capture in a loop.
Anonymous functions are declared as literals and can be assigned to variables or used immediately. If an anonymous function refers to variables from an outer scope, they are "captured" and stored for the life of the closure. As a function parameter, the anonymous function is typically passed with a func type compatible with the signature. Most problems arise with variable capture in loops — if you need to wrap logic in a closure, make sure to create a new variable inside the loop.
Example code:
func operate(nums []int, op func(int) int) []int { res := make([]int, len(nums)) for i, n := range nums { res[i] = op(n) } return res } func main() { arr := []int{1, 2, 3} out := operate(arr, func(x int) int {return x * x}) fmt.Println(out) // [1 4 9] }
Key features:
What will happen when capturing a variable with a mutable value in a loop through an anonymous function?
All closures will capture the same variable, and when the function is called after exiting the loop, you will get the same value.
Example code:
func main() { a := []func(){} for i := 0; i < 3; i++ { a = append(a, func() { fmt.Println(i) }) } for _, f := range a { f() } // 3 3 3 }
To avoid this, create a new variable in the loop body:
for i := 0; i < 3; i++ { j := i a = append(a, func() { fmt.Println(j) }) // 0 1 2 }
Can anonymous functions be used as values of type interface{}?
Functions are only compatible with interface{}, not with other interfaces, and they cannot be compared to each other (except nil). If you pass a closure as interface{}, it can only be invoked by casting it to the func signature.
Can anonymous functions be recursive?
Yes, but only if you declare a name variable for the closure first, and then assign the function to it.
Example code:
var fib func(n int) int fib = func(n int) int { if n < 2 { return n } return fib(n-1) + fib(n-2) } fmt.Println(fib(10)) // 55
In a loop over a list of callbacks, the developer binds a handler as a closure with a captured iterator variable. All callbacks work with an incorrect value, leading to bugs.
Pros:
Cons:
Inside the loop, a new variable is created for each closure, ensuring correct value capture and expected behavior.
Pros:
Cons: