Модульні уроки (5/5)
Інтерфейс помилок
error в Go — це не ключове слово: це вбудований інтерфейс із
єдиний метод.
type error interface {
Error() string
}Усе, що має Error() string, є error. У поєднанні з
угода про повернення (T, error) з функцій, це
основа обробки помилок у Go.
Дозорні помилки
import "errors"
var ErrNotFound = errors.New("non trovato")
func find(key string) (string, error) {
// ...
return "", ErrNotFound
}Sentinel – це експортоване значення error, яке абонент може
порівняти, щоб розпізнати конкретну помилку.
Спеціальні помилки (з даними)
Щоб передати контекст (наприклад, відсутній ключ), ви визначаєте тип:
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}
}errors.Is і errors.As (Go 1.13+)
Порівняння з == працює лише для «чистих» вартових. Щоб бути надійним
проти загорнутих помилок використовуйте пакет errors:
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): істинно, якщо ціль знаходиться десь у ланцюжку упаковки.errors.As(err, &target): призначає цілі першу помилку в ланцюжку свого типу.
Обтікання за допомогою %w
if err := find("k"); err != nil {
return fmt.Errorf("operazione X: %w", err)
}%w (НЕ %s або %v) створює нову помилку, яка загортає
оригінальний, зберігаючи ланцюг доступним для навігації errors.Is/As.
Шаблон обробки
v, err := op()
if err != nil {
return fmt.Errorf("op fallita per %q: %w", id, err)
}Ідіоми:
- Перевірте
err != nilнегайно, без «раннього щасливого шляху». - Додайте контекст на кожному рівні за допомогою
fmt.Errorf("... : %w", err). - «Вгору» (біля основного/обробника), розрізняйте за допомогою
errors.Is/As.
Спробуйте
Застосуйте рядок Error() для *ErrNotFound, щоб він повертав «non trovato: <Key>».
Показати підказку
`fmt.Println(err)` автоматично викликає метод Error() у вашій структурі.
Рішення доступне після 3 спроб
Використовуйте errors.Is, щоб перевірити, чи err дорівнює дозорному ErrVuoto.
Показати підказку
`errors.Is(err, target)` є надійним навіть із обгортанням ланцюжків.
Рішення доступне після 3 спроб
Яка точна сигнатура методу реалізації помилки?
func (e *MyErr) ??? {}Підведення підсумків
error = interface { Error() string }, вбудований.- Вартові з
errors.New("...")для відомих випадків без контексту. — Спеціальні типи помилок із полями для перенесення контексту. errors.Is(err, target): порівняння стійке до упаковки.errors.As(err, &target): витяжка бетонного типу.fmt.Errorf("...: %w", err): обгортка, яка зберігає ланцюг.- Ніколи не
%v/%sдля обгортання: ЗАВЖДИ використовуйте%w.