Closures
Go supports anonymous functions which can form closures. A closure is a function value that references variables from outside its body. The function may access and assign to the referenced variables.
Key Points
- Closures are anonymous functions that capture variables from their surrounding scope
- Captured variables are referenced, not copied (changes persist)
- Each closure instance maintains its own set of captured variables
- Closures extend the lifetime of captured variables
- Useful for callbacks, iterators, and maintaining state without explicit structs
- Common in goroutines to capture loop variables correctly
- Be careful with loop variables in closures - they may need explicit copies
- Closures enable functional programming patterns in Go
Basic Closure
This example shows a closure that captures and modifies a variable from its outer scope:
package main
import "fmt"
// Returns a function that generates sequential integers
func intSeq() func() int {
i := 0
return func() int {
i++ // Closure captures and modifies i
return i
}
}
func main() {
// Create a new integer sequence generator
nextInt := intSeq()
// Each call increments and returns i
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
// New closure has its own state
newInts := intSeq()
fmt.Println(newInts())
}1
2
3
1Closure as Function Argument
Closures are often used as arguments to higher-order functions or for callbacks:
package main
import "fmt"
func filter(nums []int, predicate func(int) bool) []int {
result := []int{}
for _, num := range nums {
if predicate(num) {
result = append(result, num)
}
}
return result
}
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// Closure that captures threshold value
threshold := 5
greaterThan := func(n int) bool {
return n > threshold
}
filtered := filter(numbers, greaterThan)
fmt.Println("Greater than", threshold, ":", filtered)
// Inline closure
evens := filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Println("Even numbers:", evens)
}Greater than 5 : [6 7 8 9 10]
Even numbers: [2 4 6 8 10]Closure Patterns
| Pattern | Example | Description |
|---|---|---|
| Function Generator | func() func() int | Return a closure with state |
| Inline Closure | func(n int) bool { return n > 0 } | Anonymous function capturing outer variables |
| Callback | onClick(func() { ... }) | Pass closure as callback function |
| Encapsulation | func() (get, set func()) | Return multiple closures sharing state |
| Deferred Closure | defer func() { ... }() | Capture variables for deferred execution |
Closure Characteristics
| Feature | Description | Behavior |
|---|---|---|
| Variable Capture | Closures capture variables by reference | Changes persist across calls |
| Independent State | Each closure has its own state | Multiple closures don't share captured vars |
| Lifetime | Captured variables live as long as closure exists | Prevents garbage collection of captured vars |
| Anonymous | Closures are typically anonymous functions | Defined without a name |
| First-class | Can be assigned, passed, returned | Treated like any other value |
Common Use Cases
| Use Case | Pattern | Purpose |
|---|---|---|
| Iterators | Function returning closure with state | Generate sequential values |
| Event Handlers | Closure capturing context | React to events with specific context |
| Configuration | Factory function with parameters | Create customized functions |
| Goroutines | Launch goroutine with closure | Concurrent execution with captured state |
| Deferred Cleanup | defer with closure | Resource cleanup with current state |
| Functional Programming | Map, filter, reduce patterns | Transform collections with custom logic |