2

I've been staring at this code and can't figure out the why of its behavior.

package main

import (
    "fmt"
)

var i int

func example() int {
    defer func() {
        fmt.Println("defer")
        i = 1
    }()

    fmt.Println("first")
    return i
}

func main() {
    fmt.Println(example())
    fmt.Println(i)
}

At first, the expected output for me is:

first
defer
1
1

But, as you can see in the playground the actual output is:

first
defer
0
1

Is it a deferred anonymous function behavior? Nope

So, why is it printing 0?

Vitor Falcão
  • 1,007
  • 1
  • 7
  • 18
  • 2
    The flow is `first` -> RETURN 0 -> `defer` (set i to 1) -> print return value (0) -> print i (1) - so, essentially, the zero value of `i` is captured on the return before it is updated to 1. – mukunda Mar 19 '22 at 13:01

1 Answers1

7

Does defer runs after function returns?

Certainly.

So, why is it printing 0?

Because you're returning 0.

example() returns an int by value. when return i is evaluated, is current value is returned. After that return is evaluated, the defer function executes, changing the value stored at i to 1. But the 0 value is already the return value.

Go makes it possible to modify the return value of a function, but only if the return value has a name.

For example, this returns 1:

func example() (j int) {
   defer func() { j = 1 }()
   return 0
}

But in your case, you're not naming your return variable, so you can't modify it in a defer.

erik258
  • 14,701
  • 2
  • 25
  • 31