Как работает defer с несколькими вызовами?

Junior
1.4k просмотров
AFK Offer AI

Deferred вызовы складываются в стек (LIFO — last in, first out):

func example() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    fmt.Println("main")
}
// main
// 3
// 2
// 1

Аргументы defer вычисляются сразу (в момент defer), а не при выполнении:

x := 10
defer fmt.Println(x) // напечатает 10, не 20
x = 20

Но если defer вызывает метод на указателе или замыкание — оно увидит актуальное значение:

x := 10
defer func() { fmt.Println(x) }() // напечатает 20
x = 20

Типичное использование — cleanup в обратном порядке:

f, _ := os.Open("file")
defer f.Close()
mu.Lock()
defer mu.Unlock()
Следующий вопрос

Буферизованные vs небуферизованные каналы?