延迟,return 和 golang 中的参数评估

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())
    }
}

谁能解释为什么输出从 0, 1, 1, 2, 3, 5 .... 而不是 1, 1, 2, 3, 5, ..... 开始?

据我了解,defer 会在 return 语句之前执行,这意味着 a、b 已更新为 1、1 并且 1 应该被 returned?也许它与表达式被评估或绑定的时间有关,也许 return 已经将 a 绑定为 0,然后在 returning 之前检查是否存在 defer 语句?

go 中的任何内部代码参考都会非常有帮助。

编辑 1:这是我在了解 defer 后尝试的练习 https://go.dev/tour/moretypes/26

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

如果周围的函数return通过显式return语句执行,延迟函数在该return语句设置任何结果参数之后但在函数[=17之前执行=]s 给它的调用者 Defer_statements

因为 defer 函数执行并将 a 的值从 0 更改为 1 但 a 的值已经是 return 明确的。

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

deferreturn a 之后执行,此时更改局部变量 a 的值为时已晚。

您可能将它与 defer 更改命名的 return 值混淆了。这是不同的情况,因为即使在 return 之后更改它,函数实际上也会 return 它。