Устройство defer в golang
Есть следующий кусок кода:
func f1() int {
var x int
defer func() {
x+=90
}()
x = 1
return x
}
Функция f1 всегда будет возвращать 1.
Есть другая функция:
func f2() (x int) {
defer func() {
x+=90
}()
x = 1
return
}
Функция f2 всегда будет возвращать 91.
Почему они так работают? Нигде информации не могу найти, которые бы навели меня на что грешить: на устройство работы defer или же устройство работы с переменными или и то и то.
Ответы (1 шт):
В ваших примерах отложенная функция использует переменную x из внешнего окружения. Когда компилятор ищет кандидата на добавление в замыкание, он просматривает код вверх по тексту, до первого символа с именем x, видимого в точке определения отложенной функции.
В первом примере
func f1() int {
var x int
defer func() {
x+=90
}()
первый встреченный символ x связан с внутренней переменной. Отложенная функция эту переменную обновит, но на результат это уже не повлияет, так как результат записан в стек, и (внимание) адрес области стека с возвращаемым значением не равен области, отведённой для внутренней переменной x.
Во втором примере
func f2() (x int) {
defer func() {
x+=90
}()
компилятор свяжет символ x внутри отложенной функции с символом x, обозначающим возвращаемое значение функции. Поэтому результат вычисления выражения x+=90 будет записан как раз в ту область стека, где хранится возвращаемое значение.