Defer keyword in Go-Lang

Syed Hasan
3 min readJun 7, 2021
Photo by Ryan Fields on Unsplash

Lets try to understand the defer keyword in go-lang. The defer keyword postpones the execution of a function until the surrounding function returns.It can be very useful when we have to run specific code after a function returns such as releasing resources or unsubscribing to some events.But, understanding defer function can be a little confusing at times, So lets start with the basics.

for example lets look at the code below.

package mainimport (
"fmt"
)
func main() {
defer fmt.Println("in defer function")
fmt.Println("main function over")
}

the output of the above program is as follows.

main function over
in defer function

Now we know how the defer keyword works , lets now focus on why we might want to use it. A simple example would be when we are opening a file inside a function we can use defer to close it. We can write the code to open and close the file near each other so we don’t forget to close the file and introduce unwanted bugs also the code looks much cleaner.

But what if there are multiple defer functions inside one function?

it is very important to remember that defer function is executed in last in, first out (LIFO) order, for example look at the following code.

package mainimport (
"fmt"
)
func main() {
defer fmt.Println("in defer function 1")
defer fmt.Println("in defer function 2")
defer fmt.Println("in defer function 3")
fmt.Println("main function over")
}

the output of the following code will be.

main function over
in defer function 3
in defer function 2
in defer function 1

Lets look at the diagram to better understand whats happening here.

We will be using stack data structure to explain the flow of our program, Now lets run the code sequentially if we come across a defer function we will push it on our stack. after the surrounding function is returned we we will start to pop the defer functions from our stack and start executing them.

Lets Write a function to reverse a string using defer.

i have something like this in mind.

import (
"fmt"
)
func main() {
str := "this is a string"
for i:=0;i<len(str);i++{
defer func(){
fmt.Printf("%c",str[i])
}()
}
}

Notice we have used an anonymous function without any arguments here if you try to run this code it will throw a panic (panic: runtime error: index out of range [16] with length 16) it is because when we don’t provide arguments to the defer function it will get evaluated after the execution of for loop, so when the for loop completes its execution the value if “ i ” will be 16 hence the error , but when we provide arguments to a defer function they are evaluated immediately, but the function call is not executed until the surrounding function returns and that’s exactly what we are looking for.

so lets fix the code now

package mainimport (
"fmt"
)
func main() {
str := "abcd"
for i:=0;i<len(str);i++{
defer func(c byte){
fmt.Printf("%c",c)
}(str[i])
}
}

this program produces the correct output.

dcba

--

--