Что выведет этот фрагмент и почему обёртывание вызова в замыкание меняет результат?
Прочитайте фрагмент ниже. defer fmt.Println(a) регистрируется до того, как a переприсваивается.
Определите, что он выведет, и объясните, почему обёртывание вызова в замыкание — defer func(){ fmt.Println(a) }() — изменило бы результат.
func main() {
var a int
defer fmt.Println(a)
a = 20
}
Определите вывод.
Выведет 0. defer вычисляет аргументы в момент оператора defer, фиксируя значение a (0) тогда; последующее a = 20 на него не влияет. Оберните как defer func(){ fmt.Println(a) }() — замыкание читает a при возврате и печатает 20.
- ✗Полагать, что
deferвычисляет аргументы при возврате из функции, а не при регистрации - ✗Считать, что форма с замыканием захватывает
aпо значению на оператореdefer, а не читает при возврате - ✗Путать момент вычисления аргументов с порядком LIFO выполнения отложенных вызовов
- →Если отложить вызов метода на указателе, когда вычисляется получатель?
- →Как
deferвнутри циклаforвзаимодействует с переменной цикла?
Что выведет код?
package main
import "fmt"
func main() {
var a int
defer fmt.Println(a)
a = 20
}
Выведет 0. defer fmt.Println(a) вычисляет аргумент a в момент регистрации — тогда a == 0. Это значение копируется и сохраняется вместе с отложенным вызовом; присваивание a = 20 ниже на него уже не влияет.
Чтобы напечатать 20, оберните вызов в замыкание без аргументов:
func main() {
var a int
defer func() {
fmt.Println(a) // читается при возврате → 20
}()
a = 20
}
Замыкание не вычисляет a на операторе defer — оно захватывает переменную и читает её актуальное значение в момент выполнения, то есть при возврате из функции, когда a уже равно 20.