Sentinel Hatalar
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 55 / 107.
Bir sentinel hatası, belirli bir hata durumunu temsil eden, önceden tanımlanmış, paket düzeyinde bir hata değişkenidir. errors.New ile her seferinde yeni hatalar oluşturmanın aksine, sentinel hataları bir kez tanımlanır ve kodunuz boyunca yeniden kullanılır.
Sentinel hatalarını, genellikle adları Err ile başlayan paket düzeyinde değişkenler olarak tanımlarsınız:
package user
import "errors"
var (
ErrNotFound = errors.New("user not found")
ErrInvalidEmail = errors.New("invalid email address")
ErrDuplicate = errors.New("user already exists")
)Fonksiyonlar, belirli koşullar oluştuğunda bu önceden tanımlanmış hataları döndürür:
func FindUser(id int) (*User, error) {
user, exists := users[id]
if !exists {
return nil, ErrNotFound
}
return user, nil
}Sentinel hatalarının gücü, çağıranların hata değerlerini doğrudan karşılaştırarak belirli hata durumlarını kontrol edebilmesidir:
user, err := FindUser(42)
if err == ErrNotFound {
fmt.Println("Creating new user...")
} else if err != nil {
fmt.Println("Unexpected error:", err)
}Go'nun standart kütüphanesi sentinel hataları (sentinel errors) yaygın olarak kullanır. Örneğin, io.EOF girdinin sonunu belirtir ve sql.ErrNoRows boş bir sorgu sonucunu ifade eder. Bu desen, paketler ve kullanıcıları arasında hangi hataların bekleneceği konusunda net bir sözleşme oluşturur.
Ancak, hatalar sarmalandığında basit eşitlik kontrolleri bozulur. Bir sonraki derste, errors.Is() fonksiyonunun tüm hata zincirini kontrol ederek bu sorunu nasıl çözdüğünü öğreneceksiniz.
Görev
KolayBelirli hata durumlarını iletmek için sentinel hatalarını kullanan bir envanter yönetim sistemi oluşturalım. Çağıranların farklı senaryoları uygun şekilde yönetmek için kontrol edebileceği paket düzeyinde hata değişkenleri tanımlayacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
inventory.go: Yaygın hata durumları için önceden tanımlanmış sentinel hatalarına sahip bir envanter sistemi oluşturun.Paket düzeyinde üç sentinel hatası tanımlayın:
"item not found in inventory"mesajıylaErrItemNotFound"item is out of stock"mesajıylaErrOutOfStock"insufficient quantity available"mesajıylaErrInsufficientQuantity
Öğe adlarını miktarlarıyla eşleyen bir map tutan bir
Inventorystruct'ı oluşturun. Şu metotları uygulayın:NewInventory() *Inventory- boş bir envanter oluştururAddItem(name string, quantity int)- bir öğenin miktarını ekler veya güncellerGetQuantity(name string) (int, error)- bir öğenin miktarını döndürür veya öğe mevcut değilseErrItemNotFounddöndürürPurchase(name string, quantity int) error- öğeleri satın almayı dener. Öğe mevcut değilseErrItemNotFound, mevcut miktar sıfırsaErrOutOfStockveya istenen miktar mevcut stoğu aşıyorsaErrInsufficientQuantitydöndürün. Başarılı olursa, envanteri azaltın venildöndürün.
main.go: Girdiden envanter işlemlerini okuyun ve çağıranların doğrudan eşitlik karşılaştırması kullanarak belirli sentinel hatalarını nasıl kontrol edebileceğini gösterin.Girdiden öğe adını ve satın alma miktarını okuyun. Bir envanter oluşturun,
"laptop"öğesini5miktarıyla ekleyin, ardından satın alma işlemini deneyin. Döndürülen hataya bağlı olarak, hangi sentinel hatasının oluştuğunu belirlediğinizi gösteren özel bir mesaj yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Satın alınacak öğe adı
- Satır 2: Satın alınacak miktar
Hangi spesifik hatanın döndürüldüğünü kontrol ederek sonucu yönetin:
- Eğer
err == ErrItemNotFoundise:Error: Item '[name]' does not exist in our inventoryyazdırın - Eğer
err == ErrOutOfStockise:Error: Item '[name]' is currently out of stockyazdırın - Eğer
err == ErrInsufficientQuantityise:Error: Cannot purchase [quantity] units of '[name]' - not enough in stockyazdırın - Başarılıysa:
Successfully purchased [quantity] units of '[name]'yazdırın
Örneğin, laptop ve 3 verildiğinde çıktınız şu olmalıdır:
Successfully purchased 3 units of 'laptop'Ve phone ve 2 verildiğinde çıktınız şu olmalıdır:
Error: Item 'phone' does not exist in our inventoryVe laptop ve 10 verildiğinde çıktınız şu olmalıdır:
Error: Cannot purchase 10 units of 'laptop' - not enough in stockKopya kağıdı
Bir sentinel error (nöbetçi hata), belirli bir hata durumunu temsil eden, önceden tanımlanmış, paket düzeyinde bir hata değişkenidir. Sentinel hatalar bir kez bildirilir ve kodunuz boyunca yeniden kullanılır.
Sentinel hataları, genellikle adları Err ile başlayan paket düzeyi değişkenler olarak tanımlayın:
package user
import "errors"
var (
ErrNotFound = errors.New("user not found")
ErrInvalidEmail = errors.New("invalid email address")
ErrDuplicate = errors.New("user already exists")
)Fonksiyonlar, belirli koşullar oluştuğunda bu önceden tanımlanmış hataları döndürür:
func FindUser(id int) (*User, error) {
user, exists := users[id]
if !exists {
return nil, ErrNotFound
}
return user, nil
}Çağıranlar, hata değerlerini doğrudan karşılaştırarak belirli hata koşullarını kontrol edebilirler:
user, err := FindUser(42)
if err == ErrNotFound {
fmt.Println("Creating new user...")
} else if err != nil {
fmt.Println("Unexpected error:", err)
}Go'nun standart kütüphanesi, io.EOF ve sql.ErrNoRows gibi sentinel hataları yaygın olarak kullanır.
Kendin dene
package main
import (
"fmt"
)
func main() {
// Girdiyi oku
var itemName string
var quantity int
fmt.Scanln(&itemName)
fmt.Scanln(&quantity)
// Envanter oluştur ve 5 adet "laptop" ekle
inv := NewInventory()
inv.AddItem("laptop", 5)
// TODO: Öğeyi satın almayı dene
// inv.Purchase(itemName, quantity) fonksiyonunu çağır
// TODO: Doğrudan eşitlik karşılaştırması kullanarak hangi spesifik sentinel hatasının döndüğünü kontrol et
// Kontrol etmek için if/else if ifadelerini kullan:
// - err == ErrItemNotFound
// - err == ErrOutOfStock
// - err == ErrInsufficientQuantity
// - err == nil (başarılı)
// TODO: Hataya göre uygun mesajı yazdır
// Eğer ErrItemNotFound ise: fmt.Printf("Error: Item '%s' does not exist in our inventory\n", itemName)
// Eğer ErrOutOfStock ise: fmt.Printf("Error: Item '%s' is currently out of stock\n", itemName)
// Eğer ErrInsufficientQuantity ise: fmt.Printf("Error: Cannot purchase %d units of '%s' - not enough in stock\n", quantity, itemName)
// Eğer başarılıysa: fmt.Printf("Successfully purchased %d units of '%s'\n", quantity, itemName)
}
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