Какой порядок выполнения отложенных (defer) функций в Go?

Ответ

Отложенные функции в Go, объявленные с помощью ключевого слова defer, выполняются в обратном порядке их объявления — по принципу LIFO (Last-In, First-Out). Последняя объявленная defer функция выполнится первой.

Выполнение всех отложенных функций происходит в момент, когда окружающая их функция собирается завершиться: либо через return, либо в конце блока кода, либо из-за паники.

Пример порядка выполнения:

package main

import "fmt"

func main() {
    fmt.Println("Начало main")
    defer fmt.Println("Вызов 1 (выполнится последним)")
    defer fmt.Println("Вызов 2")
    defer fmt.Println("Вызов 3 (выполнится первым)")
    fmt.Println("Конец main")
}

Вывод:

Начало main
Конец main
Вызов 3 (выполнится первым)
Вызов 2
Вызов 1 (выполнится последним)

Ключевые особенности defer:

  1. Немедленное вычисление аргументов: Аргументы для отложенной функции вычисляются в момент объявления defer, а не в момент её выполнения.

    func printArgument() {
        i := 0
        defer fmt.Println("Значение i:", i) // i = 0
        i++
        // Вывод будет "Значение i: 0", так как i было вычислено в строке с defer
    }
  2. Гарантированное выполнение: defer полезен для освобождения ресурсов (например, закрытие файлов file.Close() или разблокировка мьютексов mu.Unlock()), так как он будет выполнен даже если в функции произойдет паника.