How Defer Works
Recently I had time to read about Effective go. And then I stumbled in defer
section, I was wondering how come this code end up with this result
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
and the result is
entering: b
in b
entering: a
in a
leaving: a
leaving: b
you can try it in golang playground
let us break down the flow behind the logic.
defer un(trace("b"))
fmt.Println("in b")
a()
The question is what function do we defer
? un("b")
or trace("b")
, or both? It turn out that golang only defer
un("b")
function. That is why get get entering: b
as the result and defer
un("b")
function. After that the application will run fmt.Println(“in b")
. Next, It will execute a()
function.
defer un(trace("a"))
fmt.Println("in a")
Same as the flow before, trace("a")
will be executed first, and defer
un("a")
function. The result is entering: a
. then fmt.Println("in a")
will be run.
Now we have reach the end of application, we will take a look at defer
function.
un("b")
un("a")
because of golang defer
functions are executed in LIFO order, so un("a")
will be exectuted first, and then un("b")
the result as follow
leaving: a
leaving: b