Golang / Golang Internals and Memory Management Interview Questions
How does defer work internally in Go and what are its performance implications?
defer schedules a function call to run when the surrounding function returns — whether normally or via panic. The deferred call's arguments are evaluated immediately when the defer statement is executed, not when the deferred function runs.
// Arguments evaluated immediately at defer statement x := 10 defer fmt.Println(x) // prints 10 even if x is later changed x = 20 // Output: 10 // Named return values + defer â modify return before it reaches caller func divide(a, b float64) (result float64, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("panic: %v", r) } }() result = a / b return // named return } // LIFO order â multiple defers run last-in first-out func cleanup() { defer fmt.Println("first defer") defer fmt.Println("second defer") defer fmt.Println("third defer") // Output: third, second, first } // Performance: defer has overhead (allocates defer record pre-Go 1.14) // Go 1.14+ inlines simple defers â near-zero overhead for non-looping, non-panic paths // Avoid defer in tight loops â call cleanup explicitly func processFiles(files []string) { for _, f := range files { func() { // wrap in closure so defer fires per file fh, _ := os.Open(f) defer fh.Close() // OK inside the per-file closure // process... }() } }
Internal representation: in Go 1.14+, the compiler classifies defers as open-coded (inlined when statically determinable), stack-allocated, or heap-allocated. Open-coded defers have near-zero overhead — the compiler emits the deferred code at each return site. Only defers inside loops or under conditions that can vary at runtime fall back to the slower heap-allocated path.
More Related questions...