Какое значение будет у аргументов функции, вызванной через defer?

Ответ

Аргументы для отложенного вызова вычисляются в момент объявления 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