Menu
Coddy logo textTech

Sentinel-Fehler

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 55 von 107.

Ein Sentinelfehler ist eine vordefinierte, paketweite Fehlervariable, die eine bestimmte Fehlerbedingung darstellt. Im Gegensatz dazu, jedes Mal mit errors.New neue Fehler zu erstellen, werden Sentinelfehler einmal deklariert und im gesamten Code wiederverwendet.

Du definierst Sentinel-Fehler als Variablen auf Paketebene, typischerweise mit Namen, die mit Err beginnen:

package user

import "errors"

var (
    ErrNotFound     = errors.New("user not found")
    ErrInvalidEmail = errors.New("invalid email address")
    ErrDuplicate    = errors.New("user already exists")
)

Funktionen geben diese vordefinierten Fehler zurück, wenn bestimmte Bedingungen eintreten:

func FindUser(id int) (*User, error) {
    user, exists := users[id]
    if !exists {
        return nil, ErrNotFound
    }
    return user, nil
}

Die Stärke von Sentinel-Fehlern besteht darin, dass Aufrufer auf bestimmte Fehlerbedingungen prüfen können, indem sie Fehlerwerte direkt vergleichen:

user, err := FindUser(42)
if err == ErrNotFound {
    fmt.Println("Creating new user...")
} else if err != nil {
    fmt.Println("Unexpected error:", err)
}

Die Standardbibliothek von Go verwendet häufig Sentinel-Fehler. Beispielsweise signalisiert io.EOF das Ende der Eingabe, und sql.ErrNoRows weist auf ein leeres Abfrageergebnis hin. Dieses Muster schafft einen klaren Vertrag zwischen Paketen und ihren Benutzern darüber, welche Fehler zu erwarten sind.

Einfache Gleichheitsprüfungen schlagen jedoch fehl, wenn Fehler verpackt (wrapped) sind. In der nächsten Lektion lernen Sie, wie errors.Is() dieses Problem löst, indem es die gesamte Fehlerkette überprüft.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Bestandsverwaltungssystem, das Sentinel-Fehler verwendet, um bestimmte Fehlerbedingungen zu kommunizieren. Du definierst Fehler-Variablen auf Paketebene, die Aufrufer prüfen können, um verschiedene Szenarien angemessen zu behandeln.

Du organisierst deinen Code auf zwei Dateien verteilt:

  • inventory.go: Erstelle ein Bestandssystem mit vordefinierten Sentinel-Fehlern für häufige Fehlerfälle.

    Definiere drei Sentinel-Fehler auf Paketebene:

    • ErrItemNotFound mit der Meldung "item not found in inventory"
    • ErrOutOfStock mit der Meldung "item is out of stock"
    • ErrInsufficientQuantity mit der Meldung "insufficient quantity available"

    Erstelle eine Inventory-Struktur, die eine Map mit Artikelnamen und ihren Mengen enthält. Implementiere diese Methoden:

    • NewInventory() *Inventory – erstellt einen leeren Bestand
    • AddItem(name string, quantity int) – fügt die Menge eines Artikels hinzu oder aktualisiert sie
    • GetQuantity(name string) (int, error) – gibt die Menge eines Artikels zurück oder ErrItemNotFound, wenn er nicht existiert
    • Purchase(name string, quantity int) error – versucht, Artikel zu kaufen. Gibt ErrItemNotFound zurück, wenn der Artikel nicht existiert, ErrOutOfStock, wenn die aktuelle Menge null ist, oder ErrInsufficientQuantity, wenn die angeforderte Menge den verfügbaren Bestand überschreitet. Bei Erfolg wird der Bestand reduziert und nil zurückgegeben.
  • main.go: Lies Bestandsoperationen aus der Eingabe und demonstriere, wie Aufrufer mithilfe eines direkten Gleichheitsvergleichs auf bestimmte Sentinel-Fehler prüfen können.

    Lies den Artikelnamen und die Kaufmenge aus der Eingabe. Erstelle einen Bestand, füge den Artikel "laptop" mit der Menge 5 hinzu und versuche anschließend, den Kauf durchzuführen. Gib abhängig vom zurückgegebenen Fehler eine bestimmte Meldung aus, die zeigt, dass du erkannt hast, welcher Sentinel-Fehler aufgetreten ist.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Artikelname, der gekauft werden soll
  • Zeile 2: Kaufmenge

Behandle das Ergebnis, indem du prüfst, welcher bestimmte Fehler zurückgegeben wurde:

  • Wenn err == ErrItemNotFound: Gib Error: Item '[name]' does not exist in our inventory aus
  • Wenn err == ErrOutOfStock: Gib Error: Item '[name]' is currently out of stock aus
  • Wenn err == ErrInsufficientQuantity: Gib Error: Cannot purchase [quantity] units of '[name]' - not enough in stock aus
  • Bei Erfolg: Gib Successfully purchased [quantity] units of '[name]' aus

Wenn beispielsweise laptop und 3 eingegeben werden, sollte deine Ausgabe wie folgt aussehen:

Successfully purchased 3 units of 'laptop'

Bei der Eingabe von phone und 2 sollte deine Ausgabe wie folgt aussehen:

Error: Item 'phone' does not exist in our inventory

Bei der Eingabe von laptop und 10 sollte deine Ausgabe wie folgt aussehen:

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

Probier es selbst

package main

import (
	"fmt"
)

func main() {
	// Eingabe lesen
	var itemName string
	var quantity int
	fmt.Scanln(&itemName)
	fmt.Scanln(&quantity)

	// Inventar erstellen und "laptop" mit der Menge 5 hinzufügen
	inv := NewInventory()
	inv.AddItem("laptop", 5)

	// TODO: Versuchen, den Artikel zu kaufen
	// inv.Purchase(itemName, quantity) aufrufen

	// TODO: Überprüfen, welcher spezifische Sentinel-Fehler mittels direktem Gleichheitsvergleich zurückgegeben wurde
	// if/else if-Anweisungen verwenden, um Folgendes zu prüfen:
	// - err == ErrItemNotFound
	// - err == ErrOutOfStock
	// - err == ErrInsufficientQuantity
	// - err == nil (Erfolg)

	// TODO: Die entsprechende Nachricht basierend auf dem Fehler ausgeben
	// Wenn ErrItemNotFound: fmt.Printf("Error: Item '%s' does not exist in our inventory\n", itemName)
	// Wenn ErrOutOfStock: fmt.Printf("Error: Item '%s' is currently out of stock\n", itemName)
	// Wenn ErrInsufficientQuantity: fmt.Printf("Error: Cannot purchase %d units of '%s' - not enough in stock\n", quantity, itemName)
	// Wenn Erfolg: fmt.Printf("Successfully purchased %d units of '%s'\n", quantity, itemName)
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Go-Compiler