Ana içeriğe geç
Modül 3 · Ders 5 ders 5Kurstaki 15/50~12 min
Modül dersleri (5/5)

'erteleme': garantili temizleme

defer bir çağrının yürütülmesini çevreleyen işleve kadar erteler geri döner. Fonksiyon panik yoluyla çıksa bile çalışır. Birden çok defers aynı işlevde LIFO sırasıyla (Son Giren, İlk Çıkar) yürütülür.

Kaynak temizleme için deyimsel bir mekanizmadır: dosyaları kapatmak, mutekslerin kilidini açmak, bağlantıları serbest bırakmak, durumu geri yüklemek.

Sözdizimi ve kurallı kullanım durumu

Go
f, err := os.Open(path)
if err != nil {
    return err
}
defer f.Close()   // chiamata SEMPRE all'uscita della funzione

// ... usa f liberamente ...
return nil

Tipik: f.Close(), mu.Unlock(), db.Close(), tx.Rollback(), recover().

İddialar hemen değerlendirildi, infaz ertelendi

defer foo(x) yazdığınızda x o anda değerlendirilir. defer, yürütme sırasında değil:

Go
x := 10
defer fmt.Println(x)   // cattura 10
x = 99
// quando la funzione ritorna stampa "10", non "99"

LIFO siparişi

Ertelemeler en yenisinden başlayarak biriktirilir ve yürütülür:

Go
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1

Bu, kaynak anlambilimiyle tutarlıdır: son açılan ilk olandır kapatılacak.

defer + recover: panikle başa çıkma

defer, panic'yı engellemenin tek yoludur:

Go
func safe() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recuperato:", r)
        }
    }()
    panic("boom")
}

Tuzak: defer döngüde

defer f.Close() öğesini bir döngüye koymak, birikimleri **sonuna kadar ertelemeyi sağlar işlev **, her yinelemenin değil. Uzun bir döngüde birçok dosya açarsınız ve yalnızca işlevden çıkıldığında bunları kapatın: dosya tanımlayıcı sızıntısı riski.

Go
// MALE: defer accumulati
for _, path := range paths {
    f, _ := os.Open(path)
    defer f.Close()   // chiude TUTTI alla fine della funzione esterna
    // ...
}

// MEGLIO: estrai in una funzione
for _, path := range paths {
    elabora(path)   // ogni chiamata ha il proprio scope di defer
}

Deneyin

Egzersiz#go.m3.l5.e1
Denemeler: 0Yükleniyor…

'Sizio' yazdırın, ardından 'ince' yazdırmayı erteleme ile erteleyin, ardından 'mezzo' yazdırın. Çıktı şu şekilde olmalıdır: inizio / mezzo / fine.

Düzenleyici yükleniyor…
İpucu göster

Erteleme, main() geri dönmek üzereyken çalışır.

3 denemeden sonra çözüm mevcut

Egzersiz#go.m3.l5.e2
Denemeler: 0Yükleniyor…

Kodda 1, 2 ve 3'ü bu sırayla yazdıran ardışık üç erteleme yazın. Çıkış 3/2/1 (LIFO) olacaktır.

Düzenleyici yükleniyor…
İpucu göster

Sırayla üç erteleme; ters sırada çalıştıklarını unutmayın.

3 denemeden sonra çözüm mevcut

Quiz#go.m3.l5.e3
Hazır

Bu ne yazdırıyor? (not: erteleme argümanları hemen değerlendirilir)

Go
x := 10
defer fmt.Println(x)
x = 99
Cevap seçenekleri

Özet

  • defer call(), işlev geri dönene kadar yürütmeyi erteler.
  • Çoklu erteleme = LIFO sırası.
  • İddialar derhal değerlendirildi, infaz ertelendi.
  • Deterministik temizleme için kullanılır: dosyalar, muteksler, bağlantılar.
  • defer + recover(), panic'yi durdurur (nadir, sınırlarda).
  • Asla uzun bir döngü içinde defer: dış fonksiyon dönene kadar birikir.