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 çok katmanından geçtiğinde, bir hatanın nerede kaynaklandığını bilmek kritik hâle gelir. Go'nun fmt.Errorf işlevi ve %w fiili, hataları sarmalamanıza, bağlam eklerken özgün hatayı korumanıza olanak tanır.
Hata sarmalama bir hata zinciri oluşturur. Her katman, hata oluştuğunda ne yapmaya çalıştığı hakkında 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 fiili özeldir. Özgün hatayı yeni hatanın içine sarar. Bu, hatayı yalnızca bir dizeye dönüştüren ve özgün hatanın kimliğini kaybeden %v'den 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 kolaylaştırır.
Sarmalanmış hata hâlâ kendi içinde özgün 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 çok katmanda hata sarmalamayı gösteren bir sipariş işleme sistemi oluşturalım. Her katmanın hatalara bağlam eklediği bir işlev zinciri oluşturacak ve sorunların tam olarak nerede meydana geldiğini kolayca izleyeceksin.
Kodunu iki dosyaya ayıracaksın:
orders.go: Hatalar yukarı doğru yayılırken onları sarmalayan birden çok katmanla sipariş işleme mantığını oluştur.Bir işleme zinciri oluşturan üç işlev uygula:
ValidateItem(itemID string) error- itemID"item not found"ise"INVALID"mesajıyla bir hata döndürür, aksi durumdanildöndürürProcessOrder(orderID, itemID string) error-ValidateItemişlevini çağırır. Bir hata döndürürse hatayı şu bağlamla sarar:"processing order [orderID]: %w". Aksi durumdanildöndürürSubmitOrder(customerName, orderID, itemID string) error-ProcessOrderişlevini çağırır. Bir hata döndürürse hatayı şu bağlamla sarar:"submitting order for [customerName]: %w". Aksi durumdanildöndürür
Her katman, aşağıdaki katmandan gelen hatayı sarmalamak ve bir bağlam zinciri oluşturmak için
fmt.Errorffiiliyle birlikte%wkullanmalıdır.main.go: Sipariş ayrıntılarını girdiden oku,SubmitOrderişlevini çağır ve sonucu görüntüle. Bir hata oluşursa hata zincirinin tamamını yazdır. Başarılı olursa bir onay mesajı yazdır.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Müşteri adı
- 2. satır: Sipariş kimliği
- 3. satır: Ürün kimliği
Sonucu yazdır:
- 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 şu şekilde olmalıdır:
Error: submitting order for Alice: processing order ORD-123: item not foundHata mesajının zincirin tamamını nasıl gösterdiğine dikkat et. Sorunu üst düzey gönderim denemesinden sipariş işleme aşamasına ve oradan gerçek doğrulama hatasına kadar izleyebilirsin. Her katman, kendi bağlamını %w kullanarak ekledi.
Benzer şekilde, Bob, ORD-456 ve ITEM-001 verildiğinde çıktın şu şekilde olmalıdır:
Order ORD-456 submitted successfully for BobKendin 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ğerleriyle SubmitOrder'ı çağır
// TODO: Bir hata oluşursa yazdır: Error: [full error chain]
// TODO: If successful, print: 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 PoolKendi başına pratik yap: Online Go derleyicisi