Go core · 3 MIN READ

Two returns instead of one exception

Write a function that returns a result and an error, and read one.

Go functions can return several values. A common fallible signature returns a result followed by error; callers inspect that error before continuing with the result.

This makes ordinary failures explicit at the call site instead of using exceptions. Go also has panic and recover for exceptional control flow, but an error result is the usual contract for an expected failure. Short failure branches keep the successful path easy to read.

SEE THE IDEA

Check the error before using the value

  1. 01

    Call

    go
    value, err := load()

    The function returns both

  2. 02

    Branch

    go
    if err != nil

    Handle the failure path

  3. 03

    Continue

    go
    use(value)

    Use the successful result

The signature makes the failure path visible at the call site.

In practice

Keep the failure branch short, then let the successful path continue without extra nesting. Give the error context at the boundary where you know what operation was attempted. A function may return a useful partial result with an error only when its contract explicitly says so.

Watch out

Discarding an error with _ does not handle it. Make that choice only when the operation is known to be safe.

Official reference ↗

Work through the exercise

go
package main

import (
	"errors"
	"fmt"
)

// half returns n divided by two, and an error when n is odd.
func half(n int) (int, error) {
	// TODO: return an error when n is odd, otherwise the halved value.
	return 0, nil
}

func main() {
	value, err := half(9)
	fmt.Println(value, err)
}

var errOdd = errors.New("value is odd")
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.