Ответ
Чтобы получить доступ к результатам выполнения функции внутри defer
, необходимо использовать именованные возвращаемые значения в сочетании с анонимной функцией (замыканием).
Важно помнить ключевое правило defer
: аргументы для отложенного вызова вычисляются в момент объявления defer
, но сам вызов функции происходит при выходе из внешней функции.
Способ 1: Именованные возвращаемые значения (предпочтительный)
Если вы объявляете переменные для возвращаемых значений в сигнатуре функции, они становятся доступны внутри всей функции, включая отложенные замыкания.
func example() (result int) { // 'result' — именованное возвращаемое значение
// Анонимная функция в defer захватывает 'result' из своей области видимости.
defer func() {
// Этот код выполнится перед выходом из функции,
// когда 'result' уже будет присвоено значение 42.
fmt.Printf("Deferred call. Result is: %dn", result)
// Здесь можно даже изменить возвращаемое значение!
result++
}()
fmt.Println("Assigning result...")
return 42
}
// Вызов `example()` вернет 43, а не 42.
Способ 2: Использование указателя
Если вы не хотите использовать именованные возвращаемые значения, вы можете передать в defer
указатель на переменную с результатом.
func anotherExample() int {
var result int
// Передаем указатель на 'result' в отложенную функцию
defer func(res *int) {
fmt.Printf("Deferred call. Result is: %dn", *res)
}(&result)
result = 100
return result
}
Распространенная ошибка
Попытка передать само значение, а не использовать замыкание или указатель, приведет к тому, что в defer
будет передано значение переменной на момент объявления defer
.
func wrongExample() int {
var result int
// ОШИБКА: fmt.Println получит значение 'result' (равное 0) в ЭТОТ момент.
defer fmt.Println("Result:", result)
result = 42 // Это изменение не повлияет на значение, переданное в defer
return result
}
// Выведет: "Result: 0"