Ответ
Аргументы для отложенного вызова вычисляются в момент объявления defer
, а не в момент его выполнения.
Сама функция выполняется в конце родительской функции (перед return
), но значения её аргументов "замораживаются" в тот момент, когда компилятор встречает строку с defer
.
Пример 1: Передача по значению
func main() {
i := 0
// Значение i (равное 0) копируется и сохраняется для defer.
defer fmt.Println("Значение в defer:", i)
i++
fmt.Println("Значение в main:", i)
}
Вывод:
Значение в main: 1
Значение в defer: 0
Пример 2: Как получить актуальное значение
Чтобы defer
использовал значение переменной на момент выполнения, а не объявления, его нужно обернуть в анонимную функцию. В этом случае сама анонимная функция вызывается без аргументов, а внутри неё уже происходит обращение к актуальному значению i
.
func main() {
i := 0
// defer вызывает анонимную функцию, которая читает i в момент выполнения.
defer func() {
fmt.Println("Значение в defer (через замыкание):", i)
}()
i++
fmt.Println("Значение в main:", i)
}
Вывод:
Значение в main: 1
Значение в defer (через замыкание): 1