Mahdi.Kh
September 21, 2026
We get familiar with the concepts of Defer, Panic, and Recover in the Go (Golang) language, and learn how to use them to control program execution flow and handle errors safely.
The content and examples in this post are drawn from a post on the official Go website. For better understanding, we localized the original content and added some extra examples and explanations to it.
The defer statement pushes a function call onto a stack so that it runs after the current function finishes executing (when it returns). defer is usually used to run functions that need to be called at the end of a function's execution. Functions run using the defer statement are usually responsible for cleanup work or closing resources.
Items on the stack execute in LIFO (Last In, First Out) order; meaning the most recently added function is the first one to run. As a result, functions called with the defer statement run in reverse order at the end of the current function's execution.
In short, defer postpones a function call until the current function finishes executing.
In the example below, we copy the contents of one file into another file:
There's a bug in the example above, because if the os.Create function fails, the resource associated with the os.Open function won't be closed. In this example, the problem could be fixed by adding src.Close() before the return in the second if, but in cases where the function's logic is more complex, finding and fixing this kind of problem becomes hard.
The function above can be rewritten using the defer statement as follows:
The defer statement lets us place the code that closes each file immediately after the code that opens that file. This way, regardless of the number and location of return statements in the function, we're guaranteed that all files will be properly closed by the time the function finishes executing.
The behavior of the defer statement is quite simple. To get a good understanding of the defer statement, we need to know the points mentioned below:
The arguments of a function called with defer are evaluated at the exact moment the defer statement runs (not when the deferred function itself actually runs).
In the example above, at the moment the fmt.Println function is called via defer, the value of i is 0. So the value 0 will be printed to standard output.
Functions called using defer run, after the current function returns, in reverse order relative to when they were called — that is, last to first, or LIFO (Last In, First Out).
In the example above, the value 3210 will be printed to standard output.
Functions called with defer can access the function's named return values and, if needed, change their value.
In the example above, the function we called with defer adds one to i right before the function returns, so the value 2 is returned by the function and printed to standard output (stdout). In Go, this feature can also be used to modify the error returned from functions.
The panic function is a built-in function in Go that stops the program's normal execution flow, and if left unhandled, crashes the program.
When a function such as F calls the panic function, F's execution stops; but all the functions registered in F with the defer statement still run normally. After that, F returns to its caller, and for that caller it behaves just like a direct call to panic. This process continues up the call stack until all the functions in the current goroutine have finished; at that point, the program stops and crashes.
A panic can start directly by calling the panic function, or indirectly as the result of runtime errors such as an out-of-bounds array access.
The recover function is a built-in function in Go that lets us regain control of the execution of a goroutine that's panicking. The recover function is only useful inside functions that were called with the defer statement, and it has no effect outside of them.
During normal program execution, calling recover returns nil and has no other effect. But if the current goroutine is panicking, calling recover captures the value given to panic and resumes normal execution.
In the example above, the function g takes an integer named i, and if the value of i is greater than 3, it panics; otherwise, it calls itself again with the argument i+1. The function f also defers a function that, when it runs, calls recover and, if the returned value isn't nil, prints it. Given this, the output of the program above will be as follows:
If we remove the deferred function from f, the panic won't be recovered, and it will propagate up to the top of the goroutine's call stack. As a result, the program crashes and its execution ends. The output of the modified version of this program will be as follows:
Previous part: Generics | Golang basics
Next part: JSON | Golang basics