Go adopts a pragmatic approach to resource management. Instead of try-finally, familiar from other languages, it features defer: a built-in mechanism that records a "deferred" function and executes it upon exiting the scope. This tool is often used for automatic resource release (files, network connections).
If you forget to call Close on a file or connection, it can lead to resource leaks or deadlocks — this is critically important in server and file applications. The deferred call with defer ensures the completion function is called even when an error or panic occurs. However, there are special cases where incorrect use of defer can lead to issues: calling defer in a loop, passing an incorrect object, or working with a large number of defers can result in overhead.
Always call defer f.Close() immediately after successfully opening a resource to avoid forgotten closures. Do not use defer in tight loops for speed and memory savings if opening many files. Try to wrap file/resource opening in a function to minimize the scope.
Example code:
file, err := os.Open("data.txt") if err != nil { log.Fatal(err) } defer file.Close() // guaranteed closure // ... working with the file
Key features:
When is defer executed and when are its parameters computed?
The parameters of the deferred function are computed at the moment of defer declaration, not at the time of execution.
Example code:
func main() { a := 1 defer fmt.Println(a) // remembers 1 a = 42 } // will print 1
Can defer lead to memory leaks or slowdowns?
Yes, if defer is used in a loop where many files or objects are opened, each such defer is recorded in the stack of deferred calls, which is cleared only upon exiting the function, leading to unnecessary memory growth.
Example code:
for i := 0; i < 10000; i++ { f, _ := os.Open("file.txt") defer f.Close() // keeps all 10000 files open until main ends }
What happens if the call to f.Close() returns an error, and it is "swallowed"?
The standard practice is to log the resource closing error. If this moment is ignored, you may miss failures or partial file saves, for example, when a temporary file cannot be deleted or during network failures.
In a file processing loop, the developer places defer f.Close() for each file. As a result, tens of thousands of files are opened at once, the program slows down, and the system runs out of file descriptors.
Pros:
Cons:
In the loop, processing each file is done in a separate function, where defer f.Close() is only called once for processing and immediately releases the resource.
Pros:
Cons: