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:
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:
(int, int)after the parameters is the list of result types, in parentheses.return a / b, a % bcomputes the quotient3and the remainder2and returns both.q, r := divmod(17, 5)assigns the call to two variables:qgets the quotient,rthe remainder.fmt.Println(q, r)prints3 2.
The lists must match in two places:
- there are as many values after
returnas 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:
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:
lo, hi := minMax(8, 3)
fmt.Println(lo, hi) // 3 8Let's trace the call minMax(8, 3) step by step:
- The condition
8 < 3is false, so the function moves on. lo = bstores3inlo.hi = astores8inhi.- The naked
returnhands over the contents of both bowls, and the program prints3 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:
x := divmod(17, 5) // ✗
fmt.Println(x)assignment mismatch: 1 variable but divmod returns 2 valuesThere 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
returnhands 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
returnreturns 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.