Welcome To Golang By Example

Multiple defer functions in Go (Golang)

Overview

There can be two cases of multiple defer functions

Before we see an example for both let’s see how defer function works. When the compiler encounters a defer statement in a function it pushes it onto a list. This list internally implements a stack-like data structure.  All the encountered defer statement in the same function are pushed onto this list. When the surrounding function returns then all the functions in the stack starting from top to bottom are executed before execution can begin in the calling function. Now the same thing will happen in the calling function as well.

Now let’s see an example for both

Multiple Defer function within a particular function

In case we have multiple defer functions within a particular function, then all the  defer functions will be executed in last in first out order which is similar to what we mentioned above

Let’s see a program for that

package main
import "fmt"
func main() {
    i := 0
    i = 1
    defer fmt.Println(i)
    i = 2
    defer fmt.Println(i)
    i = 3
    defer fmt.Println(i)
}

Output

3
2
1

In the above program we have three defer function each printing the value of i. The variable i is incremented before each defer. The code outputs 3 first meaning that third defer function is executed first.  Then it outputs 2 meaning that second defer is executed after that and then it outputs 1 meaning that first defer is executed last. This shows that when there are multiple defer functions within a particular function then the follow the “Last in first out” rule. And that is why program outputs 

3
2
1

Multiple Defer function in different functions

Let’s understand what happens when we have multiple defer functions in different functions.. Imagine a function call from main function to f1 function to f2 function

main->f1->f2

Below is the sequence that will be happening after f2 returns

Let’s see a program for that

package main

import "fmt"

func main() {
	defer fmt.Println("Defer in main")
	fmt.Println("Stat main")
	f1()
	fmt.Println("Finish main")
}

func f1() {
	defer fmt.Println("Defer in f1")
	fmt.Println("Start f1")
	f2()
	fmt.Println("Finish f1")
}

func f2() {
	defer fmt.Println("Defer in f2")
	fmt.Println("Start f2")
	fmt.Println("Finish f2")
}

Output

Stat main
Start f1
Start f2
Finish f2
Defer in f2
Finish f1
Defer in f1
Finish main
Defer in main