Какие ошибки бывают в обработке ошибок в коде
Что проверяют
Знаете ли вы идиомы Go вокруг значения error и видели ли, как их нарушение ломает диагностику в проде. Следом обычно просят показать, как вы оборачиваете ошибку и как потом проверяете её выше по стеку.
Как отвечать
Называйте ошибку и сразу правильный вариант:
- игнорирование:
_ =или вызов без проверки. Коваренdefer f.Close()у файла на запись: ошибка сброса буфера теряется, и данные молча не записаны; - обёртка через
%v:fmt.Errorf("read config: %v", err)превращает ошибку в строку, иerrors.Isсerrors.Asеё уже не находят. Нужен%w. С Go 1.20 можно оборачивать несколько ошибок и собирать их черезerrors.Join, аgithub.com/pkg/errorsв новом коде не нужен, репозиторий в архиве; - сравнение через
==:err == sql.ErrNoRowsломается, как только ошибку обернули; - типизированный nil: функция возвращает
*MyError(nil)какerror, иerr != nilистинно, потому что у интерфейса есть тип; - лог и возврат сразу: одна ошибка пишется в лог на каждом уровне стека. Либо обработать и залогировать, либо обернуть и вернуть;
- затенение:
err :=во вложенном блоке создаёт новую переменную, внешняя остаётсяnil; - ошибки горутин: их никто не читает, помогает
errgroupизgolang.org/x/sync; - паника вместо ошибки:
panicдля ожидаемых ситуаций, аrecoverработает только в своей горутине, паника в чужой роняет процесс; - забытые проверки:
rows.Err()после циклаrows.Next(), закрытиеresp.Body.
Сообщения пишут со строчной буквы, без точки и с контекстом операции: open user 42: permission denied понятнее, чем failed to open.
Где спотыкаются
Используют %v и не понимают, почему errors.Is возвращает false.
Не могут объяснить ловушку с типизированным nil, хотя это один из самых частых уточняющих вопросов.
Переносят привычки из Java: предлагают исключения через panic и recover или один перехватчик на всё приложение вместо явного возврата значения.