In A Tour of Go is written:
The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.
I have difficulty in understanding the first part of the quote. What is called immediately?
func def(s string) func() {
fmt.Println("tier up")
fmt.Println(s)
return func(){ fmt.Println("clean up") }
}
func main() {
defer def("defered line")()
fmt.Println("main")
}
//Output:
//tier up
//defered line
//main
//clean up
https://play.golang.org/p/Av3mAEXxA4R
What is deferred here and what is evaluated immediately?
To learn how defer and evaluations work, first let's look at the Spec: defer statements:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
Both the function value (whose call is deferred) and its parameters are evaluated. But the deferred function is not yet called.
Let's iterate toward your example with small steps:
defer f("a")
In this case the function value is evaluated (which will be f
), and the parameters are evaluated, which is a constant, so that's gonna be "a"
.
Next step:
defer f(g("a"))
In this case the function value is evaluated (which will be f
), and the parameters are evaluated, which means g
will be called with "a"
(because g
's return value is the param to f
).
Next step:
defer f()()
This is valid if the f
function returns a function. The function value will be evaluated (which means f
will be called!) but its return value will not be called, that is what will be deferred.
defer f(g())()
In this case the deferred function is the return value of f
, so to evaluate the deferred function value, f
must be called, and to do that g
must be called prior. The return value of f
will be deferred (not called).
Back to your example:
defer def("defered line")()
The function value is evaluated, which is the return value of def
, so def
is called. The return value of def
will be deferred. Its parameters are evaluated, but actually it has no parameters.
So logically this is what happens:
def
function must be called, which requires that:
def
are evaluated, it's a constant: "defered line"
This is what happens sequentially if we lay out the above structure:
def
is evaluated: it's a constant "defered line"
def
is called which prints tier up
and its argument: defered line
def
is not called, that is what's deferred.main
prints: main
main
returns, so deferred functions are called now. The deferred function prints clean up
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