Functions are first-class values in Go: they can be assigned to variables, passed as arguments, returned from other functions, and wrapped in closures. Combined with multiple return values and defer, this gives Go a small but flexible set of function patterns.

1. Basic Functions

func add(a, b int) int {
    return a + b
}

result := add(3, 4)
fmt.Println(result) // 7

Functions declare parameter types and, when needed, a return type after the parameter list.

2. Multiple Return Values

Go commonly returns a value together with an error:

func sqrt(x float64) (float64, error) {
    if x < 0 {
        return 0, fmt.Errorf("negative number")
    }
    return math.Sqrt(x), nil
}

result, err := sqrt(16)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Println(result) // 4
}

This pattern is central to idiomatic Go error handling.

3. Named Return Values

Return values can have names:

func swap(x, y int) (first, second int) {
    first = y
    second = x
    return
}

Named returns can be useful when they improve documentation, but explicit return expressions are often easier to read in longer functions.

4. Anonymous Functions

Functions do not need a declaration name:

result := func(a, b int) int {
    return a * b
}(3, 4)

fmt.Println(result) // 12

Anonymous functions are useful for callbacks, short helpers, and goroutines.

5. Closures and Returned Functions

A function can return another function that captures values from its surrounding scope:

func createMultiplier(factor int) func(int) int {
    return func(x int) int {
        return x * factor
    }
}

double := createMultiplier(2)
fmt.Println(double(5)) // 10

The returned closure keeps access to factor even after createMultiplier returns.

6. Deferred Function Calls

defer schedules a function call to run when the surrounding function returns:

func example() {
    defer fmt.Println("printed last")
    fmt.Println("printed first")
}

It is especially useful for cleanup such as closing files or unlocking mutexes after a resource has been acquired successfully.

7. Variadic Functions

A variadic parameter accepts zero or more values of the same type:

func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

fmt.Println(sum(1, 2, 3))
fmt.Println(sum(4, 5, 6, 7, 8))

If you already have a slice, expand it with ...:

values := []int{1, 2, 3}
fmt.Println(sum(values...))

Conclusion

Go keeps function syntax deliberately compact, but the language still supports multiple results, errors, closures, anonymous functions, variadic parameters, and deferred calls. Understanding these patterns helps you write APIs that are both expressive and idiomatic.