What is the difference between named return value and normal return value?

The named return value also allocates a variable for the scope of your function.

func a() int: While you already return the value of i = 0, but since no named values was defined the static value got returned. So even though you're increasing i in the deferred function it doesn't affect the returned value.

func b() (i int): The variable i is allocated (and already initialized to 0). Even though the deferred function runs after the i = 0 was returned the scope is still accessible and thus still can be changed.


Another point of view: you can still change named return values in deferred functions, but cannot change regular return values.

This especially holds true in the following example:

func c() (i int) {
    defer func() {
        i = 1
        fmt.Println("c defer : ", i)
    }()
    return 0
}

defer runs a function after the return statement but before the function is auctually returned, thus enabling modify returned results. However, only named return results can be accessed normally, i.e. by the variable name.

The return statement, when not naked (another thing about named return, but irrelevant here), the expression got evaluated. And if the return is named, the named variable is assigned with the evaluated value.

In your code, in func a() int the return is typed but not named. So when return i is execuated, it sets the return value, a variable not available to the code, as the value of i. You can consider it as RETVAL := i. And later, your deferred function modified i but the return value (RETVAL) remains unchanged.

But in func b() (i int), i is a named return. Thus, when return i execuate, it literally translate to i = i. And later, your deffered function modified i, a return value, so the returned value change.

More on return: https://golang.org/ref/spec#Return_statements

Tags:

Go