Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does defer and named return value work?

Tags:

go

I just started learning Go and I got confused with one example about using defer to change named return value in the The Go Blog - Defer, Panic, and Recover.

The example says:

  1. Deferred functions may read and assign to the returning function's named return values.

In this example, a deferred function increments the return value i after the surrounding function returns. Thus, this function returns 2:

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

But as what I have learned from A Tour of Go - Named return values

A return statement without arguments returns the named return values. This is known as a "naked" return.

I tested in the following code and in function b it returns 1 because it wasn't the "A return statement without arguments" case mentioned above.

func a() (i int) { // return 2     i = 2     return }  func b() (i int) {  // return 1      i = 2     return 1 } 

So my question is in the first example, the surrounding function c has a named return value i, but the function c uses return 1 which in the second example we can see it should have return 1 no matter what value i is. But why after i changes in the deferred function the c function returns the value of i instead the value 1?

As I was typing my question, I might have guessed the answer. Is it because:

return 1  

is equals to:

i = 1 return  

in a function with a named return value variable i?

Please help me confirm, thanks!

like image 603
Lution Avatar asked May 16 '16 07:05

Lution


People also ask

Can defer change return value?

defer can refer to and change the return values.

Does defer run before or after return?

defer statement is a convenient way to execute a piece of code before a function returns, as explained in Golang specification: Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.

How does defer work?

A defer statement defers the execution of a function until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

How does return value work?

A return is a value that a function returns to the calling script or function when it completes its task. A return value can be any one of the four variable types: handle, integer, object, or string. The type of value your function returns depends largely on the task it performs.


1 Answers

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"
like image 182
Roy Lee Avatar answered Sep 23 '22 07:09

Roy Lee