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:
- 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!
defer can refer to and change the return values.
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.
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.
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.
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:
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With