Ответ
Вызовы, отложенные с помощью defer
, выполняются в обратном порядке их объявления — по принципу LIFO (Last-In, First-Out).
Это можно представить как стек: каждый defer
помещает свой вызов на вершину стека. Когда функция завершает свою работу (через return
или достигнув конца), Go начинает выполнять вызовы с вершины этого стека.
Пример:
package main
import "fmt"
func main() {
fmt.Println("Начало функции")
defer fmt.Println("Выполняется первым (последний defer)") // 3-й defer
defer fmt.Println("Выполняется вторым") // 2-й defer
defer fmt.Println("Выполняется третьим (первый defer)") // 1-й defer
fmt.Println("Конец функции")
}
Вывод программы:
Начало функции
Конец функции
Выполняется третьим (первый defer)
Выполняется вторым
Выполняется первым (последний defer)
Такое поведение очень удобно для управления ресурсами, например, для закрытия файла и разблокировки мьютекса в порядке, обратном их захвату.