Przejdź do głównej treści
eLearner.app
Moduł 6 · Lekcja 5 z 530/50 w kursie~14 min
Lekcje modułu (5/5)

Interfejs error

error w Go nie jest słowem kluczowym: to wbudowany interfejs z plikiem pojedyncza metoda.

Go
type error interface {
    Error() string
}

Wszystko, co ma Error() string, jest error. W połączeniu z konwencja zwracania (T, error) z funkcji, to jest podstawy obsługi błędów w Go.

Błędy Sentinela

Go
import "errors"

var ErrNotFound = errors.New("non trovato")

func find(key string) (string, error) {
    // ...
    return "", ErrNotFound
}

wartownik to wyeksportowana wartość error, którą może wywołać osoba wywołująca porównać z, aby rozpoznać konkretny przypadek błędu.

Błędy niestandardowe (z danymi)

Aby przenieść kontekst (np. brakujący klucz), definiujesz typ:

Go
type ErrNotFound struct {
    Key string
}

func (e *ErrNotFound) Error() string {
    return "non trovato: " + e.Key
}

func find(key string) (string, error) {
    return "", &ErrNotFound{Key: key}
}

błędy.Is i błędy.As (wersja 1.13+)

Porównanie z == działa tylko w przypadku „czystych” strażników. Być solidnym przed opakowanymi błędami użyj pakietu errors:

Go
import "errors"

if errors.Is(err, ErrNotFound) {
    // err IS ErrNotFound (even if wrapped)
}

var nfe *ErrNotFound
if errors.As(err, &nfe) {
    // err IS (or wraps) an *ErrNotFound; nfe points to the concrete value
    fmt.Println("chiave mancante:", nfe.Key)
}
  • errors.Is(err, target): prawda, jeśli cel znajduje się gdzieś w łańcuchu zawijania.
  • errors.As(err, &target): przypisuje cel do pierwszego błędu w łańcuchu tego typu.

Zawijanie za pomocą %w

Go
if err := find("k"); err != nil {
    return fmt.Errorf("operazione X: %w", err)
}

%w (NIE %s lub %v) tworzy nowy błąd, który zawija oryginał, utrzymując nawigację po łańcuchu za pomocą errors.Is/As.

Wzór obsługi

Go
v, err := op()
if err != nil {
    return fmt.Errorf("op fallita per %q: %w", id, err)
}

Frazeologia:

  • Sprawdź err != nil natychmiast, bez „wczesnej szczęśliwej ścieżki”.
  • Dodaj kontekst na każdym poziomie za pomocą fmt.Errorf("... : %w", err).
  • „Upstream” (w pobliżu głównego / modułu obsługi), rozróżniaj za pomocą errors.Is/As.

Spróbuj

Ćwiczenie#go.m6.l5.e1
Próby: 0Ładowanie...

Zaimplementuj ciąg Error() w *ErrNotFound, aby zwracał „non trovato: <Key>”.

Ładowanie edytora...
Pokaż wskazówkę

`fmt.Println(err)` automatycznie wywołuje metodę Error() w Twojej strukturze.

Rozwiązanie dostępne po 3 próbach

Ćwiczenie#go.m6.l5.e2
Próby: 0Ładowanie...

Użyj błędów. Służy do sprawdzania, czy err jest równy wartownikowi ErrVuoto.

Ładowanie edytora...
Pokaż wskazówkę

`errors.Is(err, target)` jest wytrzymały nawet w przypadku łańcuchów owijających.

Rozwiązanie dostępne po 3 próbach

Quiz#go.m6.l5.e3
Gotowe

Jaki jest dokładny podpis metody implementacji błędu?

Go
func (e *MyErr) ??? {}
Opcje odpowiedzi

Podsumowanie

  • error = interface { Error() string }, wbudowany.
  • Strażnicy z errors.New("...") dla znanych przypadków bez kontekstu.
  • Niestandardowe typy błędów z polami do przenoszenia kontekstu.
  • errors.Is(err, target): porównanie odporne na pakowanie.
  • errors.As(err, &target): ekstrakcja typu betonowego.
  • fmt.Errorf("...: %w", err): opakowanie chroniące łańcuch.
  • Nigdy nie zawijaj %v / %s: ZAWSZE używaj %w.