Sorunun Geçmişi:
Go 1.13'ten önce hata sadece basit bir arayüzdü. Hatalara ek bağlam eklemek için genellikle kendi türlerini oluşturuyorlardı, ancak modern Java veya C#'daki gibi yapılandırılmış bir sarma mekanizması yoktu. Go 1.13 ile birlikte hataların sarılması için standart bir yol yaratıldı, bu da fmt.Errorf fonksiyonu ile kök nedenin belirlenmesini (errors.Is/errors.As) içeriyor.
Sorun:
Hata farklı düzeylerde stack'te ortaya çıkabileceği karmaşık uygulamalarda, hatayı kodun derinliklerinden döndürürken bağlamın kaybolmaması önemlidir. Aksi takdirde, hata ayıklama zorlaşır ve zincir içinde hangi noktada hata olduğu anlaşılmaz.
Çözüm:
Go, hataları nedenleri içeren yeni hata nesnelerine sararak sarmayı sağlar. Bunun için fmt.Errorf içinde %w kullanılır ve derin nedenleri kontrol etmek için paket errors'tan errors.Is veya errors.As kullanılır.
Kod örneği:
import ( "errors" "fmt" ) var ErrNotFound = errors.New("bulunamadı") func getData() error { return fmt.Errorf("hizmet veritabanı: %w", ErrNotFound) } func main() { err := getData() if errors.Is(err, ErrNotFound) { fmt.Println("Neden tespit edildi: bulunamadı") } else { fmt.Println("Başka bir hata:", err) } }
Ana özellikler:
fmt.Errorf içinde %w kullanımı.errors.Is ve errors.As kullanımı.Hataları sararken fmt.Errorf aracılığıyla hangi formatlama operatörü kullanılmalıdır?
Doğru olan %w kullanılmalıdır, %v değil — sadece %w açma desteği sağlar.
Kod örneği:
fmt.Errorf("hata: %w", err)
fmt.Errorf olmadan hata zincirleri oluşturmak ve yine de errors.Is ile tespit etmek mümkün mü?
Hayır, Unwrap arayüzünü uygulamak gerekir, aksi takdirde standart fonksiyonlar zinciri açmaz.
Arayüz kod örneği:
type wrappedError struct { msg string err error } func (w wrappedError) Error() string { return w.msg + ": " + w.err.Error() } func (w wrappedError) Unwrap() error { return w.err }
Eğer sarılmış hata nil ise sarıldığı hata nil değerini döner mi?
Hayır, eğer sarılan hata nil ise, sarılmış hata da ancak doğru kullanımda nil olur. Ancak, hata yapısı manuel olarak oluşturulursa, hata alanı nil olsa bile nil olmayacaktır. Bu, kontrollerin yapılmasında sık sık karışıklığa neden olur.
%v kullanmak, zincirin analiz edilme yeteneğini kaybettirir.Unwrap()'ı uygulamamak.errors.Is/As ile kontrol etmemek.Uygulama her düzeyde yeni bir hata metni döndürmeyi basitçe yapıyordu:
return errors.New("veritabanına yazma hatası")
Artılar:
Eksiler:
Hataların %w ile sarılması ve errors.Is ile analiz edilmesi:
if errors.Is(err, ErrNotFound) { return fmt.Errorf("hizmet katmanı hatası: %w", err) }
Artılar:
Eksiler: