defer, fonksiyondan çıkış yapıldığında — panik veya return durumunda bile — fonksiyonun çalıştırılmasını erteleyerek çalışır. Defer, döngü içinde kullanıldığında, tüm ertelenmiş çağrılar defer çağrıları yığınında birikir ve çevreleyen fonksiyon bitiminde ters sırayla çalıştırılır.
Bu, kaynakların beklenmedik bir şekilde harcanmasına ve gecikmelere yol açabilir, çünkü tüm ertelenmiş fonksiyonlar yalnızca fonksiyonun gövdesinden çıkıldığında bir seferde çağrılacak, döngünün her bir iterasyonundan sonra değil.
Kod Örneği:
func readFiles(files []string) { for _, name := range files { f, _ := os.Open(name) defer f.Close() // kaynaklar yalnızca tüm fonksiyon tamamlandığında serbest bırakılır // dosya işleme ... } }
Bu örnekte, dosyalar fonksiyonun tamamlanmasına kadar açık kalacak, bu da çok sayıda dosya olduğunda tanımlayıcı sızıntısına yol açabilir.
Döngü içinde kaynakları kapatmak için defer kullanırsak ne olur? Bu her zaman neden optimal değildir?
Cevap: Tüm defer çağrıları birikir ve yalnızca fonksiyon tamamlandığında çalışır, her bir iterasyondan sonra değil. Bu, kaynakların (örneğin, açık dosyalar) çok geç serbest bırakılmasına neden olacaktır.
Doğru:
for _, name := range files { f, _ := os.Open(name) // defer f.Close() // yapılmamalı! // Doğru: process(f) f.Close() }
Hikaye
Log yükleme projesinde bir sorun ortaya çıktı: hizmet yeni dosyaları aniden açmayı durdurdu, oysa çok az dosya vardı. Sebep — döngüdeki defer. Tüm dosyalar açıldı ve kapatılmaları fonksiyonun sonunda ertelendi. İşlemden sonra açık Close() kullanılarak yeniden yazıldığında sorun ortadan kalktı.
Hikaye
Büyük listeler için metrik toplayan bir hizmette, verileri döngü içinde dolaşan bir döngüde veritabanı bağlantısını sıfırlamak için defer kullanıldı. İterasyon sayısı arttıkça gecikmeler ortaya çıktı ve açık bağlantı sınırları aşıldı, hizmet "çok fazla açık bağlantı" hataları vermeye başladı.
Hikaye
Bir mühendis, "şık" bir temizliğe güvenerek, çok sayıda dosyayı okuma döngüsünde defer kullandı, bu da sunucudaki açık tanımlayıcı limitinin aşılmasına ve hizmetin durmasına neden oldu.