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.

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.

challenge icon

Görev

Kolay

Belirli 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ıyla ErrItemNotFound
    • "item is out of stock" mesajıyla ErrOutOfStock
    • "insufficient quantity available" mesajıyla ErrInsufficientQuantity

    Öğ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 - öğeleri satın almayı dener. Öğe mevcut değilse ErrItemNotFound, mevcut miktar sıfırsa ErrOutOfStock veya istenen miktar mevcut stoğu aşıyorsa ErrInsufficientQuantity döndürün. Başarılı olursa, envanteri azaltın ve nil dö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" öğesini 5 miktarı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 == ErrItemNotFound ise: Error: Item '[name]' does not exist in our inventory yazdırın
  • Eğer err == ErrOutOfStock ise: Error: Item '[name]' is currently out of stock yazdırın
  • Eğer err == ErrInsufficientQuantity ise: Error: Cannot purchase [quantity] units of '[name]' - not enough in stock yazdı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 inventory

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

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

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