errors.Is() ve errors.As()
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 56 / 107.
Hatalar sarmalandığında, err == ErrNotFound gibi basit eşitlik kontrolleri artık çalışmaz. errors paketi, sarmalanmış hata zincirlerini incelemek için iki fonksiyon sağlar: errors.Is() ve errors.As().
errors.Is(), hata zincirindeki herhangi bir hatanın belirli bir sentinel hatayla eşleşip eşleşmediğini kontrol eder:
import "errors"
var ErrNotFound = errors.New("not found")
func FindUser(id int) error {
return fmt.Errorf("database lookup failed: %w", ErrNotFound)
}
err := FindUser(42)
if errors.Is(err, ErrNotFound) {
fmt.Println("User doesn't exist")
}Döndürülen hata sarmalanmış olsa bile, errors.Is() zinciri açar ve içinde ErrNotFound öğesini bulur.
errors.As(), zincirdeki herhangi bir hatanın belirli bir tür ile eşleşip eşleşmediğini kontrol eder ve onu ayıklar:
type ValidationError struct {
Field string
}
func (e *ValidationError) Error() string {
return "validation failed: " + e.Field
}
err := fmt.Errorf("request failed: %w", &ValidationError{Field: "email"})
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Println("Invalid field:", ve.Field)
}Sentinel hataları kontrol ederken errors.Is(), özel bir hata türündeki alanlara erişmeniz gerektiğinde ise errors.As() kullanın. Her iki işlev de hata zincirinin tamamını dolaşır; bu da onları sarmalanmış hataları düzgün bir şekilde ele almak için vazgeçilmez kılar.
Görev
Kolayerrors.Is() ve errors.As() kullanarak sarmalanmış hata zincirlerini nasıl doğru şekilde inceleyeceğimizi gösteren bir dosya işleme sistemi oluşturalım. Farklı katmanlardan geçerken sarmalanan hatalar oluşturacak, ardından bu işlevleri kullanarak bunları tanımlayıp içlerinden bilgi çıkaracaksın.
Kodunu iki dosyaya ayıracaksın:
errors.go: Dosya sistemin için hata altyapısını tanımla.Bir sentinel hata oluştur:
ErrPermissionDenied, mesajı"permission denied"olacak
Özel bir hata türü oluştur:
FileError(string) veFilename(string) alanlarına sahipOperationstruct'ıError()metodu şu değeri döndürmeli:[Operation] failed on file: [Filename]
Dosya işlemlerini simüle eden ve hataları sarmalayan iki işlev uygula:
ReadFile(filename string) error- filename"secret.txt"iseErrPermissionDenieddöndür. filename"missing.txt"ise Operation değeri*FileErrorve verilen Filename ile bir"read"döndür. Aksi takdirdenildöndür.ProcessFile(filename string) error-ReadFileişlevini çağırır. Bir hata döndürülürsefmt.Errorfbiçimiyle"processing failed: %w"kullanarak hatayı sarmala. Aksi takdirdenildöndür.
main.go: Girdiden bir dosya adı oku veProcessFileişlevini çağır. Sarmalanmış hata zincirini incelemek ve içinde bulduğun bilgilere göre uygun mesajları yazdırmak içinerrors.Is()veerrors.As()kullan.
Aşağıdaki girdi sağlanacaktır:
- 1. satır: İşlenecek dosya adı
Sonucu hata zincirini inceleyerek işle:
errors.Is()zincirdeErrPermissionDeniedbulursa: tam hata mesajını yazdır, ardından yeni bir satırdaAccess denied - check file permissionsyazdırerrors.As()zincirde bir*FileErrorbulursa: tam hata mesajını yazdır, ardından yeni bir satırdaFile issue: [Filename] during [Operation]yazdır- Hiç hata oluşmazsa:
File '[filename]' processed successfullyyazdır
Örneğin, secret.txt verildiğinde çıktın şöyle olmalıdır:
processing failed: permission denied
Access denied - check file permissionsVe missing.txt verildiğinde çıktın şöyle olmalıdır:
processing failed: read failed on file: missing.txt
File issue: missing.txt during readVe data.txt verildiğinde çıktın şöyle olmalıdır:
File 'data.txt' processed successfullyHatalar ProcessFile tarafından sarmalansa bile özgün sentinel hatasını errors.Is() ile hâlâ tespit edebileceğine ve özel hata türünü errors.As() ile çıkarabileceğine dikkat et. Bu işlevler, aradığın şeyi bulmak için hata zincirinin tamamını tarar.
Kendin dene
package main
import (
"errors"
"fmt"
)
func main() {
// Dosya adını girdiden oku
var filename string
fmt.Scanln(&filename)
// ProcessFile fonksiyonunu dosya adı ile çağır
err := ProcessFile(filename)
// TODO: Hata zincirini inceleyerek sonucu işle
//
// ErrPermissionDenied'ın zincirde olup olmadığını kontrol etmek için errors.Is() kullan:
// - Eğer bulunursa: tam hatayı yazdır, ardından "Access denied - check file permissions" yazdır
//
// Zincirde bir *FileError olup olmadığını kontrol etmek için errors.As() kullan:
// - Eğer bulunursa: tam hatayı yazdır, ardından "File issue: [Filename] during [Operation]" yazdır
//
// Eğer hata yoksa: "File '[filename]' processed successfully" yazdır
_ = errors.Is // ipucu: errors.Is() kullan
_ = errors.As // ipucu: errors.As() kullan
_ = err
}
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