Назад к урокам

Ключевое слово defer в Go

Урок объясняет механизм defer в Go: порядок выполнения, стек отложенных вызовов, практическое применение при работе с файлами, а также принципы использования для освобождения ресурсов и финализации операций.

Начинающий8 min

🧯 Ключевое слово 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 работают как стек --- последние откладываются, первые выполняются.
  • Это идеальный инструмент для гарантированного освобождения ресурсов.
  • Позволяет писать более чистый, безопасный и предсказуемый код.