SyntaxStudy
Sign Up
Go First-Class Functions and Closures
Go Beginner 1 min read

First-Class Functions and Closures

In Go, functions are values: they can be assigned to variables, passed as arguments, and returned from other functions. This makes higher-order functions natural to write. Function types are specified by their signature, for example `func(int, int) int`, and any function with that signature satisfies the type. A closure is a function value that captures variables from its surrounding scope. The captured variables are shared between the closure and the outer function, meaning the closure can read and modify them even after the outer function has returned. Closures are commonly used to create factories, middleware chains, and callbacks with state. Immediately invoked function expressions (IIFEs) are also valid in Go and useful for limiting the scope of variables or isolating a block of logic. Combined with defer, closures are a powerful pattern for cleanup tasks that need access to enclosing variables such as error values that are not yet known when the deferred call is registered.
Example
package main

import "fmt"

// Higher-order function: takes a function as an argument
func apply(nums []int, fn func(int) int) []int {
    out := make([]int, len(nums))
    for i, n := range nums {
        out[i] = fn(n)
    }
    return out
}

// Factory function returning a closure
func makeAdder(x int) func(int) int {
    return func(y int) int {
        return x + y
    }
}

// Closure capturing a mutable counter
func counter() (increment func(), get func() int) {
    n := 0
    increment = func() { n++ }
    get       = func() int { return n }
    return
}

func main() {
    double := func(n int) int { return n * 2 }
    nums   := []int{1, 2, 3, 4, 5}
    fmt.Println("doubled:", apply(nums, double))
    fmt.Println("squared:", apply(nums, func(n int) int { return n * n }))

    add5 := makeAdder(5)
    fmt.Println("add5(3) =", add5(3))
    fmt.Println("add5(7) =", add5(7))

    inc, get := counter()
    inc(); inc(); inc()
    fmt.Println("counter:", get()) // 3

    // IIFE
    result := func(a, b int) int { return a + b }(10, 20)
    fmt.Println("IIFE result:", result)
}