Deferred functions get executed only when the main function that contains defer statement has finished. This includes the normal exit, panic and abnormal exit so deferred functions always get executed at the end. The most common use cases of deferred functions are open/close, connect/disconnect, lock/unlock etc. kind of operations right after the main control flow. See examples below.


Examples


func main() {
fmt.Println("main: begin")
fmt.Println("main: 1")

defer child()

fmt.Println("main: 2")
fmt.Println("main: end")
}

func child() {
fmt.Println("child: begin")
fmt.Println("child: 1")
fmt.Println("child: end")
}

// main: begin
// main: 1
// main: 2
// main: end
// child: begin
// child: 1
// child: end

As shown below, all deferred functions are executed but in reverse order no matter how many times they are called.


func main() {
defer child(0)
fmt.Println("main: begin")

defer child(1)
fmt.Println("main: middle")
defer child(2)

fmt.Println("main: end")
defer child(3)
}

func child(i int) {
fmt.Printf("child: %d\n", i)
}

// main: begin
// main: middle
// main: end
// child: 3
// child: 2
// child: 1
// child: 0

One important thing to remember is that, if you need to call defer in a loop, you must move the relevant functionality into an additional function including the defer statement itself. If you don't, you would cause resource "leak". See the differences below.


// This is wrong!

func main() {
fmt.Println("main: begin")

for i := 1; i < 4; i++ {
defer child(i) // Resource leak.
}

fmt.Println("main: end")
}

func child(i int) {
fmt.Printf("child: %d\n", i)
}

// main: begin
// total: 8
// main: end
// child: 3
// child: 2
// child: 1

In the case of example above, deferred operations will have to wait for loop to finish. Hence reason it would cause resource "leak". However, the example below doesn't have such problem because, deferred operations will run immediately on each iteration. Pay attention to output.


// This correct!

func main() {
total := 1

fmt.Println("main: begin")

for i := 1; i < 4; i++ {
total = total * 2
middleman(i)
}

fmt.Printf("total: %d\n", total)
fmt.Println("main: end")
}

func middleman(i int) {
defer child(i)
}

func child(i int) {
fmt.Printf("child: %d\n", i)
}

// main: begin
// child: 1
// child: 2
// child: 3
// total: 8
// main: end