notexOPENOverview
Notex/Languages/Named Return Values
03.06LESSON 06 OF 18 · 2 MIN READ

Named Return Values

Always free to read

In addition to letting you return more than one value from a function, Go allows you to specify names for your return values. Rewrite the divAndRemainder function one more time, this time using named return values:

func divAndRemainder(num, denom int) (result int, remainder int, err error) {
    if denom == 0 {
        err = errors.New("cannot divide by zero")
        return result, remainder, err
    }
    result, remainder = num/denom, num%denom
    return result, remainder, err
}

When you supply names to your return values, what you are doing is predeclaring variables that you use within the function to hold the return values. They are written as a comma-separated list within parentheses. You must surround named return values with parentheses, even if there is only a single return value. Named return values are initialized to their zero values when created. This means that you can return them before any explicit use or assignment.

Tip

If you want to name only some of the return values, you can do so by using _ as the name for any return values you want to remain nameless.

The name you use for a named returned value is local to the function; it doesn’t enforce any name outside of the function. It is perfectly legal to assign the return values to variables of different names:

func main() {
    x, y, z := divAndRemainder(5, 2)
    fmt.Println(x, y, z)
}

While named return values can sometimes clarify your code, they do have some potential corner cases. First is the problem of shadowing, which was discussed in “Shadowing Variables”. Just as with any other variable, you can shadow a named return value. Be sure that you are assigning to the return value and not to a shadow of it.

The other problem with named return values is that you don’t have to return them. Let’s take a look at another variation on divAndRemainder. You can run it on The Go Playground:

func divAndRemainder(num, denom int) (result int, remainder int, err error) {
    // assign some values
    result, remainder = 20, 30
    if denom == 0 {
        return 0, 0, errors.New("cannot divide by zero")
    }
    return num / denom, num % denom, nil
}

Notice that you assigned values to result and remainder, then returned different values directly. Before running this code, try to guess what happens when you pass 5 and 2 to this function. The result might surprise you.

The values from the return statement are returned even though they were never assigned to the named return parameters. That’s because the Go compiler inserts code that assigns whatever is returned to the return parameters. The named return parameters give a way to declare that you intend to use variables to hold the return values, but don’t require you to use them.

Some developers like to use named return parameters because they provide additional documentation. However, I find their value to be limited. Shadowing makes them confusing, as does simply ignoring them. However, named return parameters are essential in one situation. I will talk about that when I cover defer later in the chapter.

(By the way, if you didn’t run the sample above, it returns 2 and 1.)

Progress is saved on this device.
KEEP EXPLORING

One note leads to another.

Back to the library →
⌕
Search across the entire library ⌘ K