Lekcje modułu (5/5)
Błędy: wzorzec `if err != nil`
W Go błędy to wartości, a nie wyjątki. Funkcja, która może niepowodzenie zwraca błąd jako ostatnią wartość, a osoba wywołująca go sprawdza wyraźnie. Jest jednoznaczny, przewidywalny, łatwy do przetestowania – cena taka trochę więcej gadatliwości.
Interfejs error
error to mały interfejs wbudowany w język:
type error interface {
Error() string
}Każdy typ, który implementuje Error() string, to error.
Podstawowy wzór
v, err := operazione()
if err != nil {
// gestisci o propaga
return err
}
// usa vZobaczysz to tysiące razy: jest to idiomatyczny kod dla każdego omylne wezwanie. Nie czuj się winny z powodu powtórzeń – to cecha, a nie błąd.
Błędy budowania: errors.New i fmt.Errorf
import (
"errors"
"fmt"
)
err1 := errors.New("file mancante")
err2 := fmt.Errorf("apertura %q fallita: permesso negato", path)fmt.Errorf jest idealny, jeśli chcesz dołączyć zmienne do wiadomości.
Zawijanie za pomocą %w
Aby propagować błąd dodając kontekst BEZ utraty oryginału:
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("config: %w", err)
}%w „zawija” oryginalny błąd, który można później odzyskać za pomocą
errors.Is (równość dla strażników) lub errors.As (dla typu betonu):
if errors.Is(err, os.ErrNotExist) {
// file inesistente, gestione speciale
}Błędy Sentinela
Są to błędy eksportowane jako zmienne, używane do porównań z errors.Is:
var ErrNotFound = errors.New("non trovato")
func find(id int) (Item, error) {
// ...
return Item{}, ErrNotFound
}
// chiamante:
if errors.Is(err, ErrNotFound) { ... }panic i recover (podgląd)
panic istnieje w Go, ale jest zarezerwowany dla nieodwracalnych błędów (np. błędów,
naruszone niezmienniki), a nie dla normalnego przepływu sterowania. Wejdziemy głębiej
moduł Functions z defer/recover. Na razie: nie używaj na miejscu
wzorca if err != nil.
Spróbuj
Obsłuż błąd strconv.Atoi: jeśli err != nil, wypisz go i wróć; w przeciwnym razie wydrukuj nr.
Pokaż wskazówkę
Wzór kanoniczny: sprawdź `err != nil`, zaloguj/zwróć, a następnie użyj `n`.
Rozwiązanie dostępne po 3 próbach
Zaimplementuj SafeDiv: jeśli b == 0 zwróć 0 i błędy.New('dzielenie przez zero'); w przeciwnym razie a/b i zero.
Pokaż wskazówkę
Sprawdź `b == 0` PRZED podziałem, aby uniknąć paniki w czasie wykonywania.
Rozwiązanie dostępne po 3 próbach
Jaki jest idiomatyczny wzorzec obsługi błędu w Go?
v, err := f()
// poi?Podsumowanie
errorto interfejs z jedną metodąError() string.- Wzór kanoniczny:
v, err := f(); if err != nil { return err }. - Kompiluj błędy za pomocą
errors.New(msg)lubfmt.Errorf("ctx: %w", err). - Użyj
%wdo owijania ierrors.Is/errors.Asdo sprawdzenia łańcucha. panictylko dla nieodwracalnych błędów, NIE dla normalnego przepływu sterowania.