Sentinel Hatalar
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 55 / 107.
Sentinel hatası, belirli bir hata koşulunu temsil eden, önceden tanımlanmış paket düzeyinde bir hata değişkenidir. errors.New ile her seferinde yeni hatalar oluşturmaktan farklı olarak, sentinel hataları bir kez bildirilir ve kodunuzun her yerinde yeniden kullanılır.
Sentinel hatalarını paket düzeyindeki değişkenler olarak tanımlarsın; genellikle Err ile başlayan adlar kullanılır:
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 gücü, çağıranların hata değerlerini doğrudan karşılaştırarak belirli hata koşulları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ı yaygın olarak kullanır. Örneğin, io.EOF girdinin sonunu belirtir ve sql.ErrNoRows boş bir sorgu sonucunu gösterir. Bu desen, paketler ile kullanıcıları arasında hangi hataların bekleneceğine dair açık 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 koşullarını iletmek için sentinel hataları kullanan bir envanter yönetim sistemi oluşturalım. Farklı senaryoları uygun şekilde ele almak üzere çağıranların kontrol edebileceği paket düzeyinde hata değişkenleri tanımlayacaksınız.
Kodunuzu iki dosya arasında düzenleyeceksiniz:
inventory.go: Yaygın hata durumları için önceden tanımlanmış sentinel hatalar içeren bir envanter sistemi oluşturun.Paket düzeyinde üç sentinel hata tanımlayın:
ErrItemNotFoundmesajıyla"item not found in inventory"ErrOutOfStockmesajıyla"item is out of stock"ErrInsufficientQuantitymesajıyla"insufficient quantity available"
Öğ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- öğe satın almayı dener. Öğe mevcut değilseErrItemNotFound, mevcut miktar sıfırsaErrOutOfStockveya istenen miktar mevcut stok miktarını aşıyorsaErrInsufficientQuantitydöndürün. Başarılı olursa envanteri azaltın venildöndürün.
main.go: Envanter işlemlerini girdiden okuyun ve çağıranların doğrudan eşitlik karşılaştırması kullanarak belirli sentinel hataları nasıl kontrol edebileceğini gösterin.Öğe adını ve satın alma miktarını girdiden okuyun. Bir envanter oluşturun,
"laptop"öğesini5miktarıyla ekleyin ve ardından satın alma işlemini deneyin. Döndürülen hataya göre, hangi sentinel hatanın oluştuğunu belirlediğinizi gösteren özel bir mesaj yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Satın alınacak öğenin adı
- 2. satır: Satın alınacak miktar
Sonucu, hangi özel hatanın döndürüldüğünü kontrol ederek ele alın:
err == ErrItemNotFoundise:Error: Item '[name]' does not exist in our inventoryyazdırınerr == ErrOutOfStockise:Error: Item '[name]' is currently out of stockyazdırınerr == ErrInsufficientQuantityise:Error: Cannot purchase [quantity] units of '[name]' - not enough in stockyazdırın- Başarılı olursa:
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'phone ve 2 verildiğinde çıktınız şu olmalıdır:
Error: Item 'phone' does not exist in our inventorylaptop ve 10 verildiğinde çıktınız şu olmalıdır:
Error: Cannot purchase 10 units of 'laptop' - not enough in stockKendin 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 PoolKendi başına pratik yap: Online Go derleyicisi