Menu
Coddy logo textTech

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.

challenge icon

Görev

Kolay

Birden 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 takdirde nil döndürür.
    • ProcessOrder(orderID, itemID string) error - ValidateItem fonksiyonunu çağırır. Eğer bir hata dönerse, hatayı şu bağlamla sarmalayın: "processing order [orderID]: %w". Aksi takdirde nil döndürün.
    • SubmitOrder(customerName, orderID, itemID string) error - ProcessOrder fonksiyonunu çağırır. Eğer bir hata dönerse, hatayı şu bağlamla sarmalayın: "submitting order for [customerName]: %w". Aksi takdirde nil döndürün.

    Her katman, bir alt katmandan gelen hatayı sarmalamak ve bir bağlam zinciri oluşturmak için %w fiili ile fmt.Errorf kullanmalıdır.

  • main.go: Girdiden sipariş ayrıntılarını okuyun, SubmitOrder fonksiyonunu ç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 found

Hata 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 Bob

Kopya 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
}
quiz iconKendini test et

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