🧯 Ключевое слово defer в Go
defer - это механизм, позволяющий выполнить код после завершения
функции, независимо от того, как она завершилась:
нормально, через return, или из-за ошибки.
Используется для: - освобождения ресурсов, - закрытия файлов, - финализации состояния, - журналирования.
🔹 Как работает defer
Когда вы вызываете:
defer fmt.Println("Done")
Go запоминает этот вызов, но выполняет его только после выхода из функции.
🔹 Стек вызовов defer
Все отложенные вызовы помещаются в стек. Это означает, что выполняются они в обратном порядке (LIFO).
Пример:
func one() { fmt.Println("1") }
func two() { fmt.Println("2") }
func three() { fmt.Println("3") }
func sample() {
fmt.Println("Begin")
defer one()
defer two()
defer three()
fmt.Println("End")
}
Вывод:
Begin
End
3
2
1
three() был объявлен последним --- значит, выполнится первым.
🔹 Практический пример: работа с файлами
Обычно defer используют для закрытия файлов сразу после открытия:
file, err := os.Open("sample.txt")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
Файл гарантированно будет закрыт в конце функции, даже если возникнет ошибка.
Полный пример:
file, err := os.Open("sample.txt")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
buffer := make([]byte, 30)
bytes, err := file.Read(buffer)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%c\n", bytes)
🔹 Что можно откладывать
Любой вызов функции:
- закрытие файлов,
- остановка сетевых соединений,
- освобождение мьютексов,
- восстановление после паники,
- логирование.
🔹 Итоги
deferвыполняет код, когда функция завершает работу.- Вызовы
deferработают как стек --- последние откладываются, первые выполняются. - Это идеальный инструмент для гарантированного освобождения ресурсов.
- Позволяет писать более чистый, безопасный и предсказуемый код.