Ответ
Оператор defer
планирует вызов функции (отложенный вызов), который будет выполнен непосредственно перед тем, как содержащая его функция завершит свою работу. Завершение может произойти по одной из трех причин: выполнение оператора return
, достижение конца тела функции или возникновение паники.
Ключевые особенности defer
:
-
Немедленное вычисление аргументов: Аргументы отложенной функции вычисляются в момент объявления
defer
, а не в момент ее выполнения.func main() { i := 1 defer fmt.Println("Значение i:", i) // Захватит значение i = 1 i++ fmt.Println("Текущее значение i:", i) } // Вывод: // Текущее значение i: 2 // Значение i: 1
-
Порядок выполнения LIFO (Last-In, First-Out): Если в функции несколько
defer
, они выполняются в порядке, обратном их объявлению. Последний объявленныйdefer
выполнится первым.func main() { fmt.Println("Начало") defer fmt.Println("Первый defer") defer fmt.Println("Второй defer") fmt.Println("Конец") } // Вывод: // Начало // Конец // Второй defer // Первый defer
-
Основное применение:
defer
идеально подходит для задач очистки ресурсов, таких как закрытие файлов, разблокировка мьютексов или закрытие сетевых соединений, гарантируя их выполнение вне зависимости от того, как функция завершается.func processFile(filename string) error { f, err := os.Open(filename) if err != nil { return err } defer f.Close() // Гарантированное закрытие файла // ... работа с файлом ... return nil }