2 tricky behaviors of “defer”

When discovering Golang, “defer” seems at first a little exotic.
Here is 2 situations with no obvious behavior.

Function calling a function in defer

If you want to time a function, at first sight, that may be a good idea to do :

package main
 
import (
	"fmt"
	"time"
)
 
func main() {
	start := time.Now()
	defer fmt.Println(time.Since(start))
 
	time.Sleep(100 * time.Millisecond)
}

and… wrong.

You got :

0s

Yeah, you got it.
If “defer” keep the function to call, it still calls the functions in the parameters (!)

Order of deferring

What does this code ?

package main
 
import (
	"fmt"
)
 
func main() {
	defer fmt.Println("A")
	defer fmt.Println("B")
	defer fmt.Println("C")
}
 
Answer :
<pre>
C
B
A

The “defers” accumulate as a stack.
If it makes sense theoretically, in complex functions mixing mutexes, files, etc… you could be trapped.

Of course, the specifications clear clear on these 2 points.

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. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.

“defer” is not just a syntactic sugar, it avoids a lot of redundant code and regroups the lines of code working together.
Use it !

Entrepreneur – Cofounder at Golem.ai (Paris, France)

I enjoy sharing Golang interesting patterns, experiments and tips.

Leave a Reply

Your email address will not be published. Required fields are marked *