How does defer and named return value work?

According to the Go Specification:

Return Statements A "return" statement that specifies results sets the result parameters before any deferred functions are executed.

Defer Statements "...deferred functions are invoked immediately before the surrounding function returns..."

So yes, as you assumed, the named return variable is assigned, then the deferred statement increments it.

I would add that named return parameters can lead to subtle bugs, and generally should be avoided unless there's no alternative.


A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns. -- The Go Blog: Defer, Panic, and Recover

Another way to understand the above statement:

A defer statements pushes a function call onto a stack. The stack of saved calls popped out (LIFO) and deferred functions are invoked immediately before the surrounding function returns.

 func c() (i int) {
    defer func() { i++ }()
    return 1
}

After 1 is returned, the defer func() { i++ }() gets executed. Hence, in order of executions:

  1. i = 1 (return 1)
  2. i++ (defer func pop out from stack and executed)
  3. i == 2 (final result of named variable i)

For understanding sake:

 func c() (i int) {
    defer func() { fmt.Println("third") }()
    defer func() { fmt.Println("second") }()
    defer func() { fmt.Println("first") }()

    return 1
}

Order of executions:

  1. i = 1 (return 1)
  2. "first"
  3. "second"
  4. "third"

Tags:

Go