Go Gopher How to Go

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())
}
Output:
1
2
3
1

Closure 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)
}
Output:
Greater than 5 : [6 7 8 9 10]
Even numbers: [2 4 6 8 10]

Closure Patterns

PatternExampleDescription
Function Generatorfunc() func() intReturn a closure with state
Inline Closurefunc(n int) bool { return n > 0 }Anonymous function capturing outer variables
CallbackonClick(func() { ... })Pass closure as callback function
Encapsulationfunc() (get, set func())Return multiple closures sharing state
Deferred Closuredefer func() { ... }()Capture variables for deferred execution

Closure Characteristics

FeatureDescriptionBehavior
Variable CaptureClosures capture variables by referenceChanges persist across calls
Independent StateEach closure has its own stateMultiple closures don't share captured vars
LifetimeCaptured variables live as long as closure existsPrevents garbage collection of captured vars
AnonymousClosures are typically anonymous functionsDefined without a name
First-classCan be assigned, passed, returnedTreated like any other value

Common Use Cases

Use CasePatternPurpose
IteratorsFunction returning closure with stateGenerate sequential values
Event HandlersClosure capturing contextReact to events with specific context
ConfigurationFactory function with parametersCreate customized functions
GoroutinesLaunch goroutine with closureConcurrent execution with captured state
Deferred Cleanupdefer with closureResource cleanup with current state
Functional ProgrammingMap, filter, reduce patternsTransform collections with custom logic