Ключевое слово defer
в Go откладывает выполнение функции до момента завершения окружающей функции. При наличии нескольких defer
-вызовов они выполняются в порядке LIFO (Last In, First Out) - последний добавленный defer
выполняется первым.
defer
выполняются непосредственно перед возвратом из функции:
return
выраженияfunc main() {
defer fmt.Println("First defer")
defer fmt.Println("Second defer")
defer fmt.Println("Third defer")
fmt.Println("Main function body")
}
Вывод:
Main function body
Third defer
Second defer
First defer
func example() (x int) {
defer func() { x++ }()
return 5 // Фактически вернет 6
}
func panicExample() {
defer fmt.Println("Это выполнится даже при панике")
panic("Что-то пошло не так")
defer fmt.Println("Это никогда не выполнится")
}
func loopExample() {
for i := 0; i < 3; i++ {
defer fmt.Println(i) // Будет выполнено после выхода из функции
}
}
Вывод:
2
1
0
Каждый defer
требует:
defer
для освобождения:func readFile() {
f, err := os.Open("file.txt")
if err != nil {
return
}
defer f.Close() // Гарантированное закрытие
}
defer
:func process() {
setup()
defer cleanup() // Четко видно что это парные операции
// Основная логика
}
defer
в горячих циклах - это может создать нагрузку на GCfunc complexExample() (result int) {
result = 10
defer func() {
result *= 2 // Умножает результат после return
}()
defer func(val int) {
fmt.Println("First defer:", val) // Берет result до return
}(result)
result += 5
return result // result = 15 (10 + 5)
}
Порядок выполнения:
result += 5
→ result = 15return result
(фиксируется возвращаемое значение 15)result *= 2
→ 15 * 2 = 30Вывод:
First defer: 15
Функция вернет 30
порядок выполнения defer
строго регламентирован - последний добавленный defer выполняется первым при выходе из функции. Понимание этого механизма критически важно для работы с ресурсами, обработки ошибок и написания предсказуемого кода. Особое внимание стоит уделять взаимодействию defer с возвращаемыми значениями и паникой.