ProgrammingBackend Developer

How does the defer mechanism work in loops and lambda functions in Go? What can be dangerous about using defer inside a loop?

Pass interviews with Hintsage AI assistant

Answer

defer postpones the execution of a function until the surrounding function exits — even if the exit occurs due to a panic or return. When defer is used inside a loop, all deferred calls accumulate in the defer call stack and are executed in reverse order upon completion of the surrounding function.

This can lead to unexpected resource consumption and delays, as all deferred functions will be called simultaneously only after exiting the body of the function, not after each iteration of the loop.

Code example:

func readFiles(files []string) { for _, name := range files { f, _ := os.Open(name) defer f.Close() // resources are freed only after the whole function completes // process the file ... } }

In this example, files will remain open until the end of the function execution, which can lead to descriptor leaks when dealing with a large number of files.

Trick question

What will happen if you use defer to close resources inside a loop? Why is this not always optimal?

Answer: All defer calls accumulate and will trigger only after the function completes, not after each iteration. This leads to resources (e.g., open files) being freed too late.

Correct way:

for _, name := range files { f, _ := os.Open(name) // defer f.Close() // not allowed! // Correct: process(f) f.Close() }

Examples of real errors due to lack of knowledge on the topic


Story

In the log upload project, a problem arose: the service suddenly stopped opening new files, even though there were few files. The cause was defer in the loop. All files were opened, but their closure was postponed until the end of the function. After rewriting to an explicit Close() after processing, the problem was resolved.


Story

In a service collecting metrics for large lists, defer was used to reset the database connection inside the loop of data processing. With an increase in iterations, delays and exceeding the limit of open connections occurred, leading to service crashes with "too many open connections" errors.


Story

An engineer, hoping for "elegant" cleanup, applied defer in the loop reading a large number of files, which resulted in exceeding the limit of open descriptors on the production server and stopping the service.