Go

Functions & Multiple Return Values

C functions return exactly one value — anything more requires an output pointer parameter. Go functions can return more than one value directly, no pointer trick required — a small syntax feature that turns out to be the foundation of how Go handles errors everywhere in the language.

Quick reference
What it is
Go functions can declare and return more than one value in a single return statement.
Mental model
Where C smuggles a second output value out through a pointer parameter, Go just lets a function hand back two (or more) values directly, as first-class citizens of the return statement.
Key numbers
The overwhelmingly common pattern is exactly two return values: (result, error) — covered in full in the upcoming Error Handling chapter.
Reach for it when
A function's caller genuinely needs more than one piece of information back — most often a result plus whether something went wrong.

Functions, the familiar parts

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

func multiply(a, b int) int {   // same type back-to-back: the type is written once
    return a * b
}

result := add(3, 4)   // 7

Structurally the same idea as C functions — a name, parameters, a return type, a body — with one small syntax difference: the return type comes after the parameter list, not before the function name.

Multiple return values

func divide(a, b float64) (float64, bool) {   // returns TWO values: the result, and whether it succeeded
    if b == 0 {
        return 0, false
    }
    return a / b, true
}

result, ok := divide(10, 2)
if ok {
    fmt.Println(result)   // 5
}

result2, ok2 := divide(10, 0)
if !ok2 {
    fmt.Println("division failed")   // division failed
}

Compare this to how the equivalent would look in C — an output pointer parameter, and the return value repurposed as a success/failure flag:

// C: the pointer-based equivalent
int divide(float a, float b, float *result) {
    if (b == 0) return 0;     // 0 = failure
    *result = a / b;
    return 1;                   // 1 = success
}

Go's version needs no address-of operator at the call site, no dereferencing inside the function, and no risk of a caller forgetting to pass a valid pointer — the two return values are simply there.

Named return values

A function can name its return values in the signature — they behave like pre-declared local variables, and a bare return sends back whatever they currently hold:

func divide(a, b float64) (result float64, ok bool) {
    if b == 0 {
        return   // returns the zero values: 0, false
    }
    result = a / b
    ok = true
    return   // returns result and ok, whatever they currently are
}

Useful for self-documenting what each return value means, but easy to overuse — most Go style guides recommend named returns only when they genuinely clarify the function, not as a default habit.

Variadic functions

A function can accept a variable number of arguments of the same type — Go's equivalent of the concept behind C's printf-style variadic functions, but type-safe:

func sum(numbers ...int) int {   // accepts any number of ints
    total := 0
    for _, n := range numbers {
        total += n
    }
    return total
}

sum(1, 2, 3)        // 6
sum(1, 2, 3, 4, 5)   // 15
sum()                 // 0 — zero arguments is valid too

Real-world applications

Gotchas

Field notes