Добавляйте контекст при передаче вверх
Ошибка `not found` мало полезна без понимания, что именно искали. При возврате можно обернуть её с контекстом операции, сохранив исходную причину. Это позволяет читать цепочку и одновременно проверять базовый тип через `errors.Is` или `errors.As`. Контекст должен объяснять действие: «загрузить пользователя», «прочитать конфигурацию», а не просто повторять текст нижнего уровня.
Сравнивайте причины корректно
После оборачивания прямое сравнение строк или значений часто ломается. Стандартные механизмы `errors.Is` и `errors.As` позволяют проверять известную ошибку или извлекать конкретный тип из цепочки. Это делает код устойчивее к добавлению контекста. Текст ошибки лучше оставлять для человека, а машинное ветвление строить на типах и значениях.
Обрабатывать нужно там, где есть решение
Если функция ничего не может сделать с ошибкой, чаще всего её стоит вернуть выше. Повторный запрос, перевод в HTTP-код, показ сообщения пользователю или переход на резервный источник выполняются на уровне, который знает контекст приложения. Попытка «обработать» ошибку простым логированием и продолжить работу может скрыть реальную проблему.
Логируйте один раз с нужными данными
Когда каждый слой пишет одну ошибку в журнал, один сбой превращается в пять почти одинаковых сообщений. Удобнее выбрать границу, где есть request ID, пользовательский контекст и итоговое решение, и логировать там. Секреты, токены и чувствительные данные в текст ошибки попадать не должны. Для ожидаемых ошибок уровень логирования может отличаться от действительно аварийных.
Попробуйте на практике
Постройте цепочку ошибок для загрузки конфигурации.
- Создайте функцию чтения файла, возвращающую исходную ошибку.
- На следующем уровне оберните её контекстом операции.
- Добавьте отдельную sentinel-ошибку для отсутствующего обязательного файла.
- На верхнем уровне различите её через errors.Is.
- Залогируйте итог только один раз с контекстом запуска.
Как проверить результат. Решение корректно, если причина сохраняется через wrapping, ветвление не зависит от текста сообщения, а одна ошибка не логируется многократно.
Частые вопросы
Нужно ли оборачивать каждую ошибку?
Нет. Контекст полезен, когда он добавляет новую информацию о выполняемой операции.
Почему нельзя сравнивать текст ошибки?
Текст предназначен для человека и может меняться. Для логики лучше использовать типы, значения и errors.Is/errors.As.
Где логировать ошибку?
Обычно на уровне, где принимается итоговое решение и доступен полезный контекст запроса или операции.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.