Как реализовать обработку ошибок при работе со строками и конвертацией
Что проверяют
Знаете ли вы идиому value, err и умеете ли не просто вернуть ошибку, а сохранить её причину для вызывающего кода. Следом спрашивают, чем %w отличается от %v и как отличить «не число» от «слишком большого числа».
Как отвечать
Функции strconv возвращают ошибку типа *strconv.NumError с полями Func, Num и Err. В Err лежит одна из сигнальных ошибок: strconv.ErrSyntax (строка не число) или strconv.ErrRange (число не влезает в тип).
- обёртка через
%w:fmt.Errorf("parse limit %q: %w", s, err)добавляет контекст и сохраняет цепочку. С%vцепочка рвётся, и причину выше уже не разобрать; errors.Isиerrors.As:errors.Is(err, strconv.ErrRange)отвечает на вопрос о переполнении, аerrors.As(err, &numErr)достаёт исходную строку. Пользователю это разные сообщения;- выбор функции:
Atoiудобна дляint, аParseInt(s, 10, 64)задаёт основание и разрядность явно. При переполнении она возвращаетErrRangeи максимальное по модулю значение нужного размера, поэтому приerr != nilрезультат не используют; - подготовка строки:
Atoiне обрезает пробелы, строка с пробелом в начале вернёт ошибку. Ввод сначала пропускают черезstrings.TrimSpace, знак+при этом допустим; ParseBool: принимает только фиксированный набор вроде1,t,true,TRUE, аyesилиonне пройдут;- свои ошибки: сигнальные через
errors.Newили свой тип с полями, если вызывающему нужны детали. Несколько ошибок валидации собираетerrors.Join.
Про сами строки стоит сказать отдельно: len(s) считает байты, индекс даёт байт, range идёт по рунам, а битый UTF-8 превращается в U+FFFD. Валидность проверяет utf8.ValidString.
Где спотыкаются
Пишут string(n), чтобы получить из числа строку. Для n типа int, равного 65, получится символ A, а нужен strconv.Itoa. go vet о такой конверсии предупреждает.
Используют результат, не проверив err, или молча подставляют ноль. Для пользовательского ввода «не смогли разобрать» и «ноль» это разные ситуации.
Паникуют на ошибке разбора внешних данных. panic оставляют для нарушенных инвариантов программы, а неправильный ввод это обычная ошибка.