Перейти до основного вмісту
Модуль 6 · Урок 5 із 530/50 у курсі~14 min
Модульні уроки (5/5)

Інтерфейс помилок

error в Go — це не ключове слово: це вбудований інтерфейс із єдиний метод.

Go
type error interface {
    Error() string
}

Усе, що має Error() string, є error. У поєднанні з угода про повернення (T, error) з функцій, це основа обробки помилок у Go.

Дозорні помилки

Go
import "errors"

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

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

Sentinel – це експортоване значення error, яке абонент може порівняти, щоб розпізнати конкретну помилку.

Спеціальні помилки (з даними)

Щоб передати контекст (наприклад, відсутній ключ), ви визначаєте тип:

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

errors.Is і errors.As (Go 1.13+)

Порівняння з == працює лише для «чистих» вартових. Щоб бути надійним проти загорнутих помилок використовуйте пакет 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): істинно, якщо ціль знаходиться десь у ланцюжку упаковки.
  • errors.As(err, &target): призначає цілі першу помилку в ланцюжку свого типу.

Обтікання за допомогою %w

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

%w (НЕ %s або %v) створює нову помилку, яка загортає оригінальний, зберігаючи ланцюг доступним для навігації errors.Is/As.

Шаблон обробки

Go
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.

Спробуйте

вправи#go.m6.l5.e1
Спроби: 0Завантаження…

Застосуйте рядок Error() для *ErrNotFound, щоб він повертав «non trovato: <Key>».

Завантаження редактора…
Показати підказку

`fmt.Println(err)` автоматично викликає метод Error() у вашій структурі.

Рішення доступне після 3 спроб

вправи#go.m6.l5.e2
Спроби: 0Завантаження…

Використовуйте errors.Is, щоб перевірити, чи err дорівнює дозорному ErrVuoto.

Завантаження редактора…
Показати підказку

`errors.Is(err, target)` є надійним навіть із обгортанням ланцюжків.

Рішення доступне після 3 спроб

Quiz#go.m6.l5.e3
Готовий

Яка точна сигнатура методу реалізації помилки?

Go
func (e *MyErr) ??? {}
Варіанти відповідей

Підведення підсумків

  • error = interface { Error() string }, вбудований.
  • Вартові з errors.New("...") для відомих випадків без контексту. — Спеціальні типи помилок із полями для перенесення контексту.
  • errors.Is(err, target): порівняння стійке до упаковки.
  • errors.As(err, &target): витяжка бетонного типу.
  • fmt.Errorf("...: %w", err): обгортка, яка зберігає ланцюг.
  • Ніколи не %v / %s для обгортання: ЗАВЖДИ використовуйте %w.