Hata Sarmalama (fmt.Errorf)
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 54 / 107.
Hatalar uygulamanızın birden fazla katmanından geçtiğinde, bir hatanın nereden kaynaklandığını bilmek kritik hale gelir. Go'nun %w fiili ile birlikte kullanılan fmt.Errorf fonksiyonu, bağlam eklerken orijinal hatayı koruyarak hataları sarmalamanıza olanak tanır.
Hata sarmalama bir hata zinciri oluşturur. Her katman, hata oluştuğunda ne yapmaya çalıştığına dair bilgi ekleyebilir:
func ReadConfig(filename string) error {
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("reading config file: %w", err)
}
// veriyi işle...
return nil
}%w belirteci özeldir; orijinal hatayı yenisinin içine sarar. Bu, hatayı yalnızca bir dizeye dönüştüren ve orijinal hatanın kimliğini kaybeden %v belirtecinden farklıdır.
func LoadSettings() error {
err := ReadConfig("settings.json")
if err != nil {
return fmt.Errorf("loading settings: %w", err)
}
return nil
}LoadSettings başarısız olduğunda, hata mesajı tam zinciri gösterir: "loading settings: reading config file: open settings.json: no such file or directory". Her katman bağlam ekleyerek hata ayıklamayı çok daha kolay hale getirir.
Sarmalanmış hata hala içinde orijinal hatayı barındırır. Bir sonraki derste, bu hataları nasıl açacağınızı ve errors.Is() ile errors.As() kullanarak içlerinde ne olduğunu nasıl kontrol edeceğinizi öğreneceksiniz.
Görev
KolayBirden fazla katman arasında hata sarmalamayı (error wrapping) gösteren bir sipariş işleme sistemi kuralım. Her katmanın hatalara bağlam eklediği bir fonksiyon zinciri oluşturacaksınız, bu da sorunların tam olarak nerede oluştuğunu izlemeyi kolaylaştıracaktır.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
orders.go: Hataları yukarı doğru yayılırken sarmalayan birden fazla katmana sahip sipariş işleme mantığını oluşturun.Bir işleme zinciri oluşturan üç fonksiyon uygulayın:
ValidateItem(itemID string) error- Eğer itemID"INVALID"ise"item not found"mesajıyla bir hata döndürür, aksi takdirdenildöndürür.ProcessOrder(orderID, itemID string) error-ValidateItemfonksiyonunu çağırır. Eğer bir hata dönerse, hatayı şu bağlamla sarmalayın:"processing order [orderID]: %w". Aksi takdirdenildöndürün.SubmitOrder(customerName, orderID, itemID string) error-ProcessOrderfonksiyonunu çağırır. Eğer bir hata dönerse, hatayı şu bağlamla sarmalayın:"submitting order for [customerName]: %w". Aksi takdirdenildöndürün.
Her katman, bir alt katmandan gelen hatayı sarmalamak ve bir bağlam zinciri oluşturmak için
%wfiili ilefmt.Errorfkullanmalıdır.main.go: Girdiden sipariş ayrıntılarını okuyun,SubmitOrderfonksiyonunu çağırın ve sonucu görüntüleyin. Bir hata oluşursa, tam hata zincirini yazdırın. Başarılı olursa, bir onay mesajı yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Müşteri adı
- Satır 2: Sipariş ID
- Satır 3: Ürün ID
Sonucu yazdırın:
- Bir hata oluşursa:
Error: [full error chain] - Başarılı olursa:
Order [orderID] submitted successfully for [customerName]
Örneğin, Alice, ORD-123 ve INVALID verildiğinde çıktınız şu şekilde olmalıdır:
Error: submitting order for Alice: processing order ORD-123: item not foundHata mesajının tam zinciri nasıl gösterdiğine dikkat edin; sorunu en üst düzey gönderim girişiminden, sipariş işleme yoluyla, gerçek doğrulama hatasına kadar izleyebilirsiniz. Her katman %w kullanarak kendi bağlamını eklemiştir.
Ve Bob, ORD-456 ve ITEM-001 verildiğinde çıktınız şu şekilde olmalıdır:
Order ORD-456 submitted successfully for BobKopya kağıdı
Orijinal hatayı korurken hataları sarmalamak için %w fiili ile fmt.Errorf kullanın:
func ReadConfig(filename string) error {
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("reading config file: %w", err)
}
return nil
}%w fiili, hatayı yalnızca bir dizeye dönüştüren ve orijinal hatanın kimliğini kaybetmesine neden olan %v'nin aksine, orijinal hatayı yenisinin içine sarmalar.
Hata sarmalama, her katmanın bağlam eklediği bir zincir oluşturur:
func LoadSettings() error {
err := ReadConfig("settings.json")
if err != nil {
return fmt.Errorf("loading settings: %w", err)
}
return nil
}Sonuçta ortaya çıkan hata mesajı tüm zinciri gösterir: "loading settings: reading config file: open settings.json: no such file or directory"
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Müşteri adını oku
scanner.Scan()
customerName := scanner.Text()
// Sipariş ID'sini oku
scanner.Scan()
orderID := scanner.Text()
// Ürün ID'sini oku
scanner.Scan()
itemID := scanner.Text()
// TODO: Giriş değerleri ile SubmitOrder fonksiyonunu çağır
// TODO: Bir hata oluşursa şunu yazdır: Error: [full error chain]
// TODO: Başarılı olursa şunu yazdır: Order [orderID] submitted successfully for [customerName]
_ = customerName
_ = orderID
_ = itemID
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker Pool