Original post

Learn about ’s defer statement with various usage examples.

What is defer?

It takes a func and executes it just before* the surrounding func returns whether there is a panic or not.

Prints: “first” than “later”

👉 Go doesn’t need destructors because it has no built-in constructors. This is a good balance.

👉 Defer resembles to finally” however the defer belongs to the surrounding “func” while the finally belongs to an exception “block”.

👊 Bonus: See my comment here about the internals of defer if you’re curious about how it works. It’s actually been documented pragmatically as “it runs — after — the surrounding func returns”, however, there are some other inner details.

Releasing acquired resources

Defer funcs are often used to release the acquired resources inside a func.

The func closes the opened file whether there is an error or not on all returns — marked with the star.

Save us from panic

Defer can recover from a panic to prevent the termination of a program if the panic emitted from the same goroutine.

recover() returns the value provided to panic() which lets you decide what you’d do with it. You can also pass an error or other types of values to panic, then you can check whether the panic was caused by the value you’re looking for. More here.

Deferred closure

A deferred func can be of any type of func. So, when used with an anonymous func — obviously — the func becomes aware of its surroundings.

Notice that it sees the state of the surrounding values, check out:

Understand how a defer func sees its context

Params evaluation

Go runtime will save any passed params to the deferred func at the time of registering the defer— not when it runs.


Declare a dummy func that registers a deferred closure. It also uses a named result value “n” to increase the passed number for the second time:

func count(i int) (n int) {
  defer func(i int) {
n = n + i
  i = i * 2
n = i

Let’s try:

// output: 30

What happened?

Parse the visual following the numbers (on the left): 1, 2, 3.

In some situations defer can help you to change the result value before the return by using the named result values as seen in the example.

Multiple defers

Multiple defers are saved in a stack list. So, the last registered defer will run as the first. Beware: Using multiple defers may hinder the readability.



To understand how multiple defers work

Watch how it works

The animation loops

Deferred methods

You can also use methods with defer. However, there’s a quirk. Watch.

Without pointers

type Car struct {
model string
func (c Car) PrintModel() {
func main() {
c := Car{model: "DeLorean DMC-12"}
  defer c.PrintModel()
  c.model = "Chevrolet Impala"


DeLorean DMC-12

With Pointers

func (c *Car) PrintModel() {


Chevrolet Impala

What’s going on?

Remember that the passed params to a deferred func are saved aside immediately without waiting for the deferred func to be run.

So, when a method with a value-receiver is used with defer, the receiver will be copied (in this case Car) at the time of registering and the changes to it wouldn’t be visible (Car.model). Because the receiver is also an input param and evaluated immediately to “DeLorean DMC-12” when it’s registered with the defer.

On the other hand, when the receiver is a pointer when it’s called with defer, a new pointer is created but the address it points to would be the same with the “c” pointer above. So, any changes to it would be reflected flawlessly.

Alright, that’s all for now. Thank you for reading so far.

Let’s stay in touch:

Go Defer Simplified with Practical Visuals was originally published in Learn Go Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.