Skip to content
Theory · Functions · lesson 3 of 10

Multiple results

In the previous lesson the function appliance handed out one dish. But some appliances have two outlets: a juicer gives you both juice and pulp from one run.

Division with a remainder also gives two numbers—the quotient and the remainder. A function with one result would return only one of them, and the other would need a second function. In Go a function returns several values at once:

GO
package main

import "fmt"

func divmod(a, b int) (int, int) {
    return a / b, a % b
}

func main() {
    q, r := divmod(17, 5)
    fmt.Println(q, r) // 3 2
}

The result list

Let's walk through the example step by step:

  1. (int, int) after the parameters is the list of result types, in parentheses.
  2. return a / b, a % b computes the quotient 3 and the remainder 2 and returns both.
  3. q, r := divmod(17, 5) assigns the call to two variables: q gets the quotient, r the remainder.
  4. fmt.Println(q, r) prints 3 2.

The lists must match in two places:

  • there are as many values after return as there are types in the list, in the same order;
  • the call is assigned to the same number of variables.

Go often uses this to return a result together with information about whether the action succeeded. Many standard library functions return a (T, error) pair: a value of some type T and an error.

The blank identifier _

When a call is assigned to variables, every result must be received. A value you don't need is replaced by the blank identifier _.

The line q, _ := divmod(17, 5) keeps the quotient and discards the remainder, like pulp that goes straight into the bin. With an ordinary variable instead of _, the program would not compile unless that variable is read later.

This is where the juicer analogy ends. You can leave the pulp in the juicer and forget about it. In an assignment you can't: each result must go into a variable or be thrown away explicitly with _.

Named results

Results can be given names: (lo, hi int). Picture labelled bowls placed under the appliance's outlets in advance.

Named results are variables declared at the start of the function. They have three properties:

  • they are visible throughout the function's body;
  • until the first assignment they hold the zero values of their types: the bowls stand empty;
  • the names tell the reader which result comes first.

Their values can be returned in two ways, and the function minMax shows both:

GO
func minMax(a, b int) (lo, hi int) {
    if a < b {
        return a, b
    }
    lo = b
    hi = a
    return
}

return with values

The statement return a, b works the same as in a function without names. It stores a in lo and b in hi and returns them right away. In minMax this branch runs when a is already less than b.

This way suits any function. In long functions it is better to list the values explicitly: the reader doesn't have to look for what is in the bowls.

Naked return

A return with no values, a naked return, returns the current values of the named results. Let's look at a call:

GO
lo, hi := minMax(8, 3)
fmt.Println(lo, hi) // 3 8

Let's trace the call minMax(8, 3) step by step:

  1. The condition 8 < 3 is false, so the function moves on.
  2. lo = b stores 3 in lo.
  3. hi = a stores 8 in hi.
  4. The naked return hands over the contents of both bowls, and the program prints 3 8.

A naked return is handy in short functions, where all the bowls are in view at a glance.

Interviewers like to ask what a naked return returns when nothing was assigned to a named result. The answer: the zero value of its type, such as 0 for int. A naked return neither loses nor ignores anything—it hands over whatever is in the bowls at that moment.

Common mistake

A call to a function with two results was assigned to one variable:

GO
x := divmod(17, 5) // ✗
fmt.Println(x)
TEXT
assignment mismatch: 1 variable but divmod returns 2 values

There must be as many variables on the left as the function has results. Write q, r := divmod(17, 5), and replace a value you don't need with _.

Key points

  • A function can return several values: their types are listed in parentheses, and return hands them back separated by commas.
  • In an assignment, each result goes into a variable or is discarded with _.
  • Named results are variables that start at their zero values, and a naked return returns their current values.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way