Отсрочка, возврат и оценка аргумента в 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 должен быть возвращен? Может быть, это как-то связано с тем, когда выражение оценивается или связывается, может быть, возврат уже связал a как 0, а затем проверяет непосредственно перед возвратом, есть ли операторы отсрочки?

Любая внутренняя ссылка на код в go будет очень полезна.

Изменить 1: это из упражнения https://go.dev/tour/moretypes/26 , которое я попробовал после того, как узнал об отсрочке.

2 ответа

Может кто-нибудь объяснить, почему вывод начинается с 0, 1, 1, 2, 3, 5 .... вместо 1, 1, 2, 3, 5, .....?

если окружающая функция возвращается через явный оператор возврата, отложенные функции выполняются после того, как любые параметры результата установлены этим оператором возврата, но до того, как функция вернется к вызывающей стороне Defer_statements

Потому что функция отсрочки выполняется и изменяет значение a с 0 на 1, но значение a уже является явным возвращаемым значением.

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

Выполняется после return aкогда слишком поздно менять значение локальной переменной a.

Вы наверное путаете с deferизменение именованного возвращаемого значения. Это другой случай, потому что даже изменение его после return, функция фактически вернет его.

Другие вопросы по тегам