Как происходит обработка ошибок в Go
Что проверяют
Понимаете ли вы, что ошибка это значение, и знаете ли современные средства работы с ней.
Как отвечать
В Go нет исключений для обычных ошибок: функция возвращает error последним значением, и вызывающий обязан его проверить.
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("чтение конфигурации %s: %w", path, err)
}Ключевые практики:
- оборачивание с контекстом:
%wвfmt.Errorfсохраняет исходную ошибку в цепочке. Без него причина теряется, и в логе остаётся бесполезное «no such file»; - сравнение:
errors.Is(err, os.ErrNotExist)идёт по всей цепочке, а не сравнивает верхний уровень. Прямое сравнение через==ломается, как только ошибку обернули; - извлечение типа:
errors.As(err, &target)достаёт конкретный тип из цепочки, чтобы прочитать поля; - свои типы ошибок реализуют интерфейс
error, а для оборачивания методUnwrap; - сигнальные ошибки:
var ErrNotFound = errors.New("не найдено")для сравнения черезerrors.Is; errors.Joinобъединяет несколько ошибок, например при валидации формы.
Паника это не механизм обработки ошибок, а сигнал о неисправимом состоянии. Её ловят через recover в defer только на границе: в HTTP-обработчике, чтобы одна паника не уронила весь сервер.
Про многословность стоит сказать честно: if err != nil действительно занимает много места, и это осознанный компромисс. Взамен виден каждый путь отказа, а не только счастливый.
Где спотыкаются
Игнорируют возвращённую ошибку.
Оборачивают через %v вместо %w и рвут цепочку.
Сравнивают ошибки через == после оборачивания.
Используют панику как замену исключениям.