Defer Function

Defer Function

In this tutorial, we are going to discuss about defer functions in Go language. Defer Function is an amazing addition to Go language.

Defer Function

defer is a keyword in Go language that makes a function executes at the end of the execution of parent function or when parent function hits return statement.

Let’s dive into the example to understand better.

package main

import "fmt"

func sayDone() {
	fmt.Println("Finally I am done..!!")
}

func main() {
	fmt.Println("Main function execution started..!!")

	defer sayDone()

	fmt.Println("Main function execution completed..!!")
}

Output

Main function execution started..!!
Main function execution completed..!!
Finally I am done..!!

You can run above program in Go Playground

As main function executes, it will print Main function execution started..!! and then hits sayDone function but keeps in the waiting list because of defer function. Then it prints Main function execution completed..!! and as main function stops executing, sayDone() gets executed.

We can pass parameters to defer function if it supports but there is a hidden gotcha. Let’s create a simple function with arguments.

package main

import "fmt"

func endTime(timestamp string) {
	fmt.Println("Program ended at", timestamp)
}

func main() {
	time := "10 AM"

	defer endTime(time)

	time = "11 AM"

	fmt.Println("Doing Something")
	fmt.Println("Main function finished")
	fmt.Println("Now time is", time)
}

Output

Doing Something
Main function finished
Now time is 11 AM
Program ended at 10 AM

You can run above program in Go Playground

In the above example, we deferred execution of endTime function which means it will get executed at the end of main function but since at the end main function, time === "11 AM", we were expecting Program ended at 11 AM message.

Even though because of deferred execution, endTime function is executing at the end of main function, it was pushed into the stack with all available argument values earlier when time variable was still 10 AM.

Stack follows Last In First Out (LIFO) order of execution. Which means, any task pushed first, will execute in the end.

Let’s write multiple deferred tasks and see what I mean

package main

import "fmt"

func greet(message string) {
	fmt.Println("greeting: ", message)
}

func main() {
	fmt.Println("Call one")
	defer greet("Greet one")
	fmt.Println("Call two")
	defer greet("Greet two")
	fmt.Println("Call three")
	defer greet("Greet three")
}

Output

Call one
Call two
Call three
greeting:  Greet three
greeting:  Greet two
greeting:  Greet one

You can run above program in Go Playground.

Practical use of defer can be seen when a function has too many conditions whether if-else or case statements, and at the end of each condition, you need to do something like close a file or send http response. Instead of writing multiple calls, we can use defer to save the day.

Below is an example of a bad program.

if cond1 {
    ...
    fs.Close(file)
} else if cond2 {
    ...
    fs.Close(file)
} else if cond3 {
    ...
    fs.Close(file)
} else {
    ...
    fs.Close(file)
}

Below is an example of a good program.

defer fs.Close(file)
if cond1 {
    ...
} else if cond2 {
    ...
} else if cond3 {
    ...
} else {
    ...
}

Defer Function


Scroll to top