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
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // chiamata SEMPRE all'uscita della funzione
// ... usa f liberamente ...
return nilTipik: 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:
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:
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1Bu, 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:
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.
// 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
'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.
İpucu göster
Erteleme, main() geri dönmek üzereyken çalışır.
3 denemeden sonra çözüm mevcut
Kodda 1, 2 ve 3'ü bu sırayla yazdıran ardışık üç erteleme yazın. Çıkış 3/2/1 (LIFO) olacaktır.
İpucu göster
Sırayla üç erteleme; ters sırada çalıştıklarını unutmayın.
3 denemeden sonra çözüm mevcut
Bu ne yazdırıyor? (not: erteleme argümanları hemen değerlendirilir)
x := 10
defer fmt.Println(x)
x = 99Ö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.