Получить доступ

Как в Go обрабатывают ошибки и зачем нужны errors.Is, errors.As и %w?

JuniorОшибки и panic
Ещё спрашивают так:
  • Почему в Go нет исключений?
  • Как обернуть ошибку в Go, сохранив исходную?
Коротко

Ошибка — обычное значение типа error, которое функция возвращает последним: if err != nil { return ... }. Оборачивают с контекстом через fmt.Errorf("...: %w", err). Проверяют errors.Is (совпадение с конкретной ошибкой в цепочке) и errors.As (найти ошибку нужного типа).

  • Сравнение err == ErrNotFound не работает для обёрнутых — только errors.Is
  • Сигнальные ошибки: var ErrNotFound = errors.New("not found")
  • Свой тип ошибки — для данных (код, поле)

А ещё errors.Join (1.20) — объединить несколько ошибок

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Почему значения, а не исключения. Путь ошибки виден в коде явно: каждая функция, которая может упасть, это показывает, а вызывающий решает, что делать. Нет скрытых переходов через несколько уровней стека. Цена — многословность.

Оборачивание. %w сохраняет исходную ошибку внутри новой; цепочка раскручивается errors.Unwrap. Сообщение получается вида «repo.Get 42: dial tcp: connection refused» — контекст каждого уровня. %v вместо %w добавит текст, но разорвёт цепочку для Is и As.

Правила:

  • обрабатывать ошибку один раз: либо вернуть с контекстом, либо залогировать, но не оба;
  • не игнорировать (_ = f()) без явной причины;
  • не сравнивать по тексту err.Error();
  • сигнальные ошибки — часть API пакета, менять их нельзя.

Пример

var ErrNotFound = errors.New("not found")

func (r *Repo) Get(id int) (*User, error) {
    u, err := r.db.query(id)
    if errors.Is(err, sql.ErrNoRows) {
        return nil, ErrNotFound
    }
    if err != nil {
        return nil, fmt.Errorf("repo.Get %d: %w", id, err)
    }
    return u, nil
}

if errors.Is(err, ErrNotFound) { http.Error(w, "нет", 404) }

var ve *ValidationError
if errors.As(err, &ve) { log.Println(ve.Field) }

Что хотят услышать

  • Ошибки как значения.
  • Оборачивание через %w.
  • errors.Is и errors.As.
  • Правила обработки.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем