Defer Functions in Golang: Common Mistakes and Best Practices

Reza Khademi
4 min readSep 20, 2023

--

A Deep Journey in Golang: Defer Functions!

This story will focus on defer functions in Golang, providing a comprehensive guide to help us understand them better.

In Golang, defer functions give us the ability to execute a statement just after the surrounding function ends. It’s a logical delay that can help us run a task after a function exits, regardless of an error occurs or not.

Let’s see en example:

Defer Functions Golang

We should know defer statements will run in LIFO (Last In, First Out) order:

And when there is a panic:

It is very important to understand defer functions will run after panic at the end of surrounding function. So, when we want to recover from a panic situation, we should use a deferred function as shown below to catch the panic error: (Again, note LIFO order)

No “panic happened” is printed because panic recovered by recover(). The call to recover() works only if it's called directly in deferred function and it should not be used to call another func.

Let’s Go further

Now that we have a fundamental knwoledge of the defer functions and statements, let’s dive into some practical use cases.

1. Common Mistake: Immediate defer Close()

Imagine a scenario where we’re dealing with a file. After doing some certain operations, we might write a defer call as below:

Common Mistake Golang defer Close()

This approach is quite wrong and if the file creation fails the file variable might be nil, which will lead the program to a runtime panic. We want to improve this, but the following attempt is still incorrect:

I’m not gonna lie to you, this code will usually run without any error but if something bad happens, it will cost you a headache to understand what is wrong!

Because when we use the defer keyword before a function, we are ignoring any potential error it might return. This makes our code less predictable and harder to debug over time!

As the saying goes, third time’s the charm, and let’s get it right: (Obviously, you can extract the anonymous func into another function)

Not only this scenario, but any other action like calling an API and closing HTTP response body and etc can make your application to start to behave abnormal!

2. For Loop and Defers

Another thing to be cautious about is writing defer functions inside for loops. Look at this example:

We expected the first printed value to be 0, but using defer keyword will delay the result, stack them and by LIFO behavior the result will be 43210.

If we have a file closing defer statement inside a for loop, we must know that closing the desired resource won’t happen until execution of surrounding function ends. For example:

Golang defer function and for loops

The code above can cause a resource leaks or random results. There are multiple ways to fix current issue and one of them could be using an anonymous function like this:

Golang defer functions

So, that’s it. Here is the summary of what we have reviewed so far.

Summary

  • We can use defer for recover from a panic
  • Calling to recover() function works only if it's called directly in deferred function
  • We can delay some statement to run at the end of surrounding function
  • Defer functions will not return error to handle them directly
  • We should Be careful about for loops and defer functions to avoid resource leaks

If you like this article please Clap 👏 and follow me to get more of these Golang stories.

ALSO READ:

--

--