godeferred-executionvariable-binding

Defer, return and Argument evaluation in golang


package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        defer func() {a, b = b, a + b}()
        return a
    }
}

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}

Can someone explain why the output starts from 0, 1, 1, 2, 3, 5 .... instead of 1, 1, 2, 3, 5, .....?

As I understand defer would be executed before return statement which means a, b is updated to 1, 1 already and 1 should be returned? Maybe it has something to do with when the expression is evaluated or binded, maybe the return has already binded a as 0 and then check just before returning if defer statements are there?

Any internal code reference in go would be highly helpful.

Edit 1: This is from the exercise https://go.dev/tour/moretypes/26 which I tried after learning about defer.


Solution

  • The defer gets executed after return a when it is too late to change the value of local variable a.

    You are probably confusing it with defer changing a named return value. That's a different case because even changing it after return, the function will actually return it.