Functions as Values

Overview

In Go, functions are first-class citizens—they can be assigned to variables, passed as arguments, and returned from other functions.

Function Variables

// Assign function to variable
add := func(a, b int) int {
    return a + b
}

result := add(2, 3)  // 5

// Reassign
add = func(a, b int) int {
    return a + b + 1  // Different implementation
}

Function Types

type BinaryOp func(int, int) int

var op BinaryOp = func(a, b int) int {
    return a + b
}

Higher-Order Functions

Functions as Parameters

func apply(nums []int, fn func(int) int) []int {
    result := make([]int, len(nums))
    for i, n := range nums {
        result[i] = fn(n)
    }
    return result
}

double := func(n int) int { return n * 2 }
result := apply([]int{1, 2, 3}, double)  // [2, 4, 6]

Functions as Return Values

func multiplier(factor int) func(int) int {
    return func(n int) int {
        return n * factor
    }
}

double := multiplier(2)
triple := multiplier(3)

double(5)  // 10
triple(5)  // 15

Common Patterns

Callback Pattern

func fetchData(url string, callback func(data []byte, err error)) {
    // Async operation
    go func() {
        data, err := http.Get(url)
        callback(data, err)
    }()
}

Option Pattern

type Server struct {
    port    int
    timeout time.Duration
}

type Option func(*Server)

func WithPort(p int) Option {
    return func(s *Server) { s.port = p }
}

func WithTimeout(t time.Duration) Option {
    return func(s *Server) { s.timeout = t }
}

func NewServer(opts ...Option) *Server {
    s := &Server{port: 8080, timeout: 30 * time.Second}
    for _, opt := range opts {
        opt(s)
    }
    return s
}

srv := NewServer(WithPort(9000), WithTimeout(time.Minute))

Middleware Pattern

type Handler func(http.ResponseWriter, *http.Request)

func WithLogging(h Handler) Handler {
    return func(w http.ResponseWriter, r *http.Request) {
        log.Printf("%s %s", r.Method, r.URL)
        h(w, r)
    }
}

Anonymous Functions

// Immediate invocation (IIFE)
result := func(x int) int {
    return x * x
}(5)  // 25

// In goroutines
go func() {
    fmt.Println("async")
}()

Summary

Pattern Use Case
Function variable Store/swap implementations
Higher-order Transform, filter, reduce
Closures Capture state
Options Flexible configuration