В КУРСЕ?

Разбираемся в теме

Работа с ошибками в Go: wrapping, проверка и границы ответственности

Ошибки в Go являются обычными значениями, поэтому качество обработки зависит от архитектуры, а не от исключений, которые автоматически поднимаются вверх. Хороший код решает два вопроса: где добавить контекст и где принять решение. Нижний уровень обычно сообщает, что пошло не так, а верхний знает, что делать пользователю или сервису. Если каждый слой одновременно логирует и оборачивает одну ошибку, журналы превращаются в шум.

Добавляйте контекст при передаче вверх

Ошибка `not found` мало полезна без понимания, что именно искали. При возврате можно обернуть её с контекстом операции, сохранив исходную причину. Это позволяет читать цепочку и одновременно проверять базовый тип через `errors.Is` или `errors.As`. Контекст должен объяснять действие: «загрузить пользователя», «прочитать конфигурацию», а не просто повторять текст нижнего уровня.

Сравнивайте причины корректно

После оборачивания прямое сравнение строк или значений часто ломается. Стандартные механизмы `errors.Is` и `errors.As` позволяют проверять известную ошибку или извлекать конкретный тип из цепочки. Это делает код устойчивее к добавлению контекста. Текст ошибки лучше оставлять для человека, а машинное ветвление строить на типах и значениях.

Обрабатывать нужно там, где есть решение

Если функция ничего не может сделать с ошибкой, чаще всего её стоит вернуть выше. Повторный запрос, перевод в HTTP-код, показ сообщения пользователю или переход на резервный источник выполняются на уровне, который знает контекст приложения. Попытка «обработать» ошибку простым логированием и продолжить работу может скрыть реальную проблему.

Логируйте один раз с нужными данными

Когда каждый слой пишет одну ошибку в журнал, один сбой превращается в пять почти одинаковых сообщений. Удобнее выбрать границу, где есть request ID, пользовательский контекст и итоговое решение, и логировать там. Секреты, токены и чувствительные данные в текст ошибки попадать не должны. Для ожидаемых ошибок уровень логирования может отличаться от действительно аварийных.

Попробуйте на практике

Постройте цепочку ошибок для загрузки конфигурации.

  1. Создайте функцию чтения файла, возвращающую исходную ошибку.
  2. На следующем уровне оберните её контекстом операции.
  3. Добавьте отдельную sentinel-ошибку для отсутствующего обязательного файла.
  4. На верхнем уровне различите её через errors.Is.
  5. Залогируйте итог только один раз с контекстом запуска.

Как проверить результат. Решение корректно, если причина сохраняется через wrapping, ветвление не зависит от текста сообщения, а одна ошибка не логируется многократно.

Частые вопросы

Нужно ли оборачивать каждую ошибку?

Нет. Контекст полезен, когда он добавляет новую информацию о выполняемой операции.

Почему нельзя сравнивать текст ошибки?

Текст предназначен для человека и может меняться. Для логики лучше использовать типы, значения и errors.Is/errors.As.

Где логировать ошибку?

Обычно на уровне, где принимается итоговое решение и доступен полезный контекст запроса или операции.

Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.

Зарегистрируйтесь, чтобы уточнить возможность доступа к этому материалу

Зарегистрироваться
← К списку материалов