Menu
Coddy logo textTech

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.

challenge icon

Görev

Kolay

Belirli 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:

    • ErrItemNotFound mesajıyla "item not found in inventory"
    • ErrOutOfStock mesajıyla "item is out of stock"
    • ErrInsufficientQuantity mesajıyla "insufficient quantity available"

    Öğe adlarını miktarlarıyla eşleyen bir map tutan bir Inventory struct'ı oluşturun. Şu metotları uygulayın:

    • NewInventory() *Inventory - boş bir envanter oluşturur
    • AddItem(name string, quantity int) - bir öğenin miktarını ekler veya günceller
    • GetQuantity(name string) (int, error) - bir öğenin miktarını döndürür veya öğe mevcut değilse ErrItemNotFound döndürür
    • Purchase(name string, quantity int) error - öğe satın almayı dener. Öğe mevcut değilse ErrItemNotFound, mevcut miktar sıfırsa ErrOutOfStock veya istenen miktar mevcut stok miktarını aşıyorsa ErrInsufficientQuantity döndürün. Başarılı olursa envanteri azaltın ve nil dö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" öğesini 5 miktarı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 == ErrItemNotFound ise: Error: Item '[name]' does not exist in our inventory yazdırın
  • err == ErrOutOfStock ise: Error: Item '[name]' is currently out of stock yazdırın
  • err == ErrInsufficientQuantity ise: Error: Cannot purchase [quantity] units of '[name]' - not enough in stock yazdı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 inventory

laptop ve 10 verildiğinde çıktınız şu olmalıdır:

Error: Cannot purchase 10 units of 'laptop' - not enough in stock

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)
}
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

Kendi başına pratik yap: Online Go derleyicisi