Menu

Golang Multiple Return Values: (value, error), Named Results

Go functions can return several values. This page covers the syntax, the (value, error) convention, the comma-ok idiom, named results, naked returns and the blank identifier.

This page includes runnable editors - edit, run, and see output instantly.

Returning more than one value

List the result types in parentheses. Return the values separated by commas, and receive them the same way.

The built-in min and max exist since Go 1.21. The caller must receive every result: x := minMax(nums) fails to compile with assignment mismatch: 1 variable but minMax returns 2 values.

The (value, error) convention

The most common reason to return two values is to report failure. By convention the error comes last, and when it is non-nil the other results should be treated as meaningless.

Output:

port: 8080
error: port "http": strconv.Atoi: parsing "http": invalid syntax
error: port out of range

On failure return the zero value for every other result (0, "", nil). The full pattern, including wrapping and checking, is on the error handling page.

The comma-ok idiom

Several built-in operations return an optional second bool that says whether the first value is real. The variable is conventionally named ok.

These three forms (map lookup, type assertion, channel receive) are special: they return one value or two depending on how many variables you assign to. Your own functions cannot do that. A function declared with two results always returns two.

The blank identifier

_ receives a value and throws it away. Use it for results you do not need:

_, err := fmt.Sscan(input, &n)
key, _ := parseLine(line)

Ignoring an error with _ compiles, so do it only when you know the call cannot fail or failure does not matter. strings.Builder.WriteString always returns a nil error, for example; a file close after writing does not.

Named results

Result parameters can have names. They are declared at the start of the function, initialized to their zero values, and a return with no values returns whatever they hold.

The names appear in go doc output, which helps when two results share a type: (quotient, remainder int) says more than (int, int).

A bare return in a long function is hard to read, because the reader has to scan back to see what the results hold. The usual advice: name results when the names document something, and still write return quotient, remainder explicitly unless the function is a few lines long.

Named results and defer

A deferred function runs after the return statement has set the results and before the caller receives them. With named results, the deferred function can read and change them. This is how you add context to any error a function returns, or turn a panic into an error.

This prints load : empty name and then <nil>. return errors.New(...) first assigns to err, then the deferred function wraps it. More on this in defer.

Shadowing a named result

Named results live in the function's outermost scope. A := inside a nested block creates a new variable with the same name, and a bare return then returns the outer one.

func find() (n int, err error) {
	if true {
		n, err := compute() // new n and err, shadowing the results
		_ = n
		_ = err
	}
	return // returns 0, nil
}

The compiler catches the worst case: a bare return inside the block where a result is shadowed fails with result parameter err not in scope at return. It does not catch the version above, where the return sits outside the block. Use = instead of := when you mean the result variables.

Common mistakes

  • Using the value when err is non-nil. Check err first. A function is free to return garbage alongside an error.
  • Returning a typed nil pointer as an error. var e *MyErr; return e returns a non-nil error. Return a literal nil on success.
  • Too many results. Three or more results of mixed meaning are hard to use. Return a struct instead.

Frequently Asked Questions

How do you return multiple values from a function in Go?

List the result types in parentheses and return the values separated by commas: func minMax(xs []int) (int, int) { ...; return lo, hi }. The caller assigns them all at once: lo, hi := minMax(nums).

How do I ignore one of the return values in Go?

Assign it to the blank identifier _: _, err := strconv.Atoi(s) or n, _ := strconv.Atoi(s). You cannot leave a value out entirely: the number of variables on the left must match the number of results.

What are named return values in Go?

Result parameters that have names, like func split(n int) (half, rest int). They start at their zero values, can be assigned in the body, and a bare return returns their current values. They also let a deferred function change what the caller receives.

Should I use naked returns in Go?

Only in short functions. A bare return in a long function hides what is being returned and makes shadowing bugs easy. The Go style guides recommend naming results for documentation and returning explicit values in anything longer than a few lines.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED