ProgramlamaBackend Geliştirici

Go'da hata yönetimi nasıl uygulanmaktadır, Go neden kendi hata işleme modelini seçti ve hataların günlük programlamada kullanılmasına dair en iyi uygulamalar nelerdir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Konunun geçmişi:

Go, hataların değerler olarak ele alındığı, istisnaların olmadığı bir hata işleme yaklaşımıyla diğer birçok dilden farklılık göstermektedir. Bu tasarım, şeffaflık ve basitlik amacıyla seçilmiştir: Bir şeyin ters gitmesi durumunda, fonksiyon açıkça bir hata olarak ikinci bir dönüş değeri döndürür.

Problemi:

Birçok yeni başlayan, Go'ya alışık oldukları try-catch kalıplarını uygulamaya çalışırken, hataların çok sayıda kontrolü arasında kaybolmakta veya bağlamı iletmek için hata sarmalamayı kullanmamaktadır. Bu, bilgilendiriciliğin kaybına ve zor bir hata ayıklamaya neden olmaktadır.

Çözümü:

Go'da hata döndürebilen bir fonksiyon şu şekilde tanımlanır:

func doSomething() (ResultType, error) { // ... if somethingWrong { return nil, errors.New("bir şeyler yanlış gitti") } return result, nil }

Hata kontrolü çağıran tarafın sorumluluğundadır:

res, err := doSomething() if err != nil { log.Fatalf("işlem başarısız: %w", err) }

Go 1.13 ve sonrası, hata zincirleri oluşturmak için fmt.Errorf("%w", err) ile hataları "sarmalamaya" izin verir. Bu, teşhisi iyileştirir ve hataların bağlamsal açıklamalarıyla en iyi uygulamayı destekler.

Ana özellikler:

  • Hatalar, işlevler tarafından döndürülen değerlerdir (try/catch yok)
  • Kendi hata türlerinizi oluşturabilirsiniz (error arayüzünü kullanarak)
  • Hata sarmalama, hata ayıklama ve günlüklemeyi daha şeffaf hale getirir

Kandırmaca soruları.

Kendi hata türlerinizi oluşturmanın anlamı nedir, neden sadece errors.New("...") döndürmemek gerekir?

Doğru cevap: Kendi hata türleri, yalnızca hata metnini bildirmekle kalmaz, aynı zamanda ek bilgileri (örneğin, dönüş kodları, bağlam) saklamayı da sağlar ve type assertion ile daha ince işleme imkanı sunar.

Örnek:

type NotFoundError struct { Resource string } func (e NotFoundError) Error() string { return fmt.Sprintf("%s bulunamadı", e.Resource) } // Kontrol if _, ok := err.(NotFoundError); ok { // arama hatasını işleme }

Panic, kritik hatalar için error yerine iyi bir alternatif midir?

Hayır, Go'da panic yalnızca gerçekten çıkılmaz durumlar için kullanılır — örneğin, programın hataları (program içi invariants) için, fakat normal hatalar (örneğin, dosya açılamadı) için değildir. Gündelik hataları bildirmek için panic kullanmak, kötü bir uygulamadır ve okunması zor, yönetilemez koda yol açar.

Eğer return, iç fonksiyonlarda hata işlemeyi atlarsa ne olur?

Hata "kaybolur", kod çalışmaya devam eder, bu da hatalı bir durumun yayılmasına neden olabilir. Her hata dönüşünü düzgün bir şekilde işlemek her zaman önemlidir.

Tipik hatalar ve anti-patlemler

  • _ = ... ile dönen hataların göz ardı edilmesi
  • Hata hakkında akış kontrolü için panic/recover kullanımı
  • Bağlam mesajı ile iletilmeyen hataların yeniden yönlendirilmesi

Gerçek hayattan bir örnek

Olumsuz bir durum

Her fonksiyon yalnızca errors.New(...) döndürür, hatalar sarılmamıştır, hata türleri farklıdır, ancak işleme her zaman aynıdır — günlüklenir ve fırlatılır. Sonuç olarak, log dosyaları bilgi verici olmayan mesajlarla doludur, bunların kaynağa kadar izlenmesi imkansızdır.

Artıları:

  • Hızlı kod yazma
  • İşlem için daha az kod

Eksileri:

  • Kötü izleme
  • Hataların türüne göre filtreleyebilme veya ayırt edebilme imkânı yoktur

Olumlu bir durum

Hatalar, fmt.Errorf("%w", err) ile sarılır, özel hatalar yararlı alanlarla oluşturulur, errors.Is()/errors.As() ile kontroller yapılır. Bu sayede, detaylarla günlükleme yapılabilir, iş hataları çevresel hatalardan ayrılabilir ve güvenilir bir yeniden deneme mantığı yazılabilir.

Artıları:

  • Kullanışlı hata ayıklama
  • Daha temiz kod
  • Hataların esnek işlenmesi

Eksileri:

  • Daha fazla kod ve şablon mantığı
  • Hata türlerini desteklemek gerekir