Defer, return and Argument evaluation in golang

686 Views Asked by At
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.

2

There are 2 best solutions below

0
On BEST ANSWER

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.

0
On

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

if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller Defer_statements

Because the defer function executes and changes the value of a from 0 to 1 but the value of a is already the return explicit.

func fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        defer func() {a, b = b, a + b}()
        return a
    }
}