The Defer Statement

Chapter 9

In languages like C, we often need to free up reserved memory resources - commonly seen when using malloc and free which allocates and deallocates memory respectively.

In Go, we pair allocation and deallocation of memory together. For example, if you want to open a network or Input-Output (IO) connection, you can use the defer keyword on the closeConnection() call. closeConnection() will be deferred to the point where it is exiting the function.

The utility of this comes here: Imagine that you opened the connection and have a close connection at the end of the function. However, if there is an exception in between these 2 statements, then the close connection call will never be called. That will mean that the allocated resources are never freed and will be kept occupied unnecessarily.

In a way, this is similar to the finally block in Java, which ensures that the code in the finally block will be executed.

Personally, it is also a simple and effective way to remember to close connections, because now in the next line that follows an openConnection() call, I can immediately write defer closeConnection().

Note: defer can only be used for a function call. For example,defer x--, where x is a variable, is not allowed and will throw an error.

In the following example, using defer postpones the second function call to addOne() to the end of the function.

func addOne(x *int) {
*x += 1
func main() {
x := 10
fmt.Println(x) // prints 11
defer addOne(&x)
fmt.Println(x) // also prints 11

Also, defer runs in last-in-first-out (LIFO) order. For example,

// this prints 1,2,3,4,5 in order
func main() {
defer fmt.Println(5)
defer fmt.Println(4)
defer fmt.Println(3)
defer fmt.Println(2)
defer fmt.Println(1)