ProgrammingGo Developer

Explain how defer works in Go and when the order of calls can become unexpected. What pitfalls are encountered in practice?

Pass interviews with Hintsage AI assistant

Answer.

The defer keyword in Go postpones the execution of specified functions until the surrounding function exits — functions accumulate in a stack and are executed in reverse order (LIFO). This is often used for resource cleanup (files, mutexes, connections).

A feature is that all arguments of the functions passed to defer are evaluated immediately at the moment of declaration, not at execution time.

func test() { for i := 0; i < 3; i++ { defer fmt.Println(i) // Will print: 2, 1, 0 } }

Trick question.

What will the following code output?

func main() { for i := 0; i < 3; i++ { defer fmt.Println(i) } }

Answer:

It will output:

2
1
0

Because during each iteration, the argument i is evaluated immediately (at the moment of defer), and all values are stored in the defer stack.

Examples of real errors due to ignorance of the intricacies of the topic.


Story

In a file service, it was forgotten that defer is only called on normal exit from a function. Leaks appeared if the program crashed before the defer call.


Story

In a data pipeline, there was a forgetting — defer was used in a loop to close connections, but they actually closed only after the entire function finished, not after each iteration. This led to resource exhaustion.


Story

In a logger, defer was used with an anonymous function, expecting the argument to be evaluated at the time of the call. As a result, the log at the end contained outdated information, as the values were captured earlier.