Тип error: возврат, проверка и оборачивание
Содержание курса
В прошлом уроке функция divide сигнализировала о делении на ноль вторым возвращаемым значением типа bool. Это работало, но информация скудная: вызывающий код знает лишь «что-то пошло не так», а не почему. Go решает эту проблему типом error — он несёт текстовое описание причины сбоя и встроен в язык как первоклассный интерфейс.
Интерфейс error: контракт, nil и соглашение о позиции
В Go error определён примерно так:
type error interface {
Error() string
}
Это встроенный интерфейс с одним методом. Любой тип, реализующий Error() string, автоматически удовлетворяет этому интерфейсу — никаких явных объявлений не нужно.
Ключевой момент: нулевое значение интерфейса — nil. Именно nil — единственный способ сказать «всё прошло успешно». Если функция вернула nil в позиции error, значит сбоя не было.
Посмотрите на типичную сигнатуру:
func validatePositive(n int) (int, error)
Здесь два возвращаемых значения. Если error не равен nil, нужно обработать ошибку и использовать остальные возвращаемые значения только так, как разрешает контракт конкретной функции. Например, validatePositive при ошибке возвращает 0 просто как неиспользуемое значение — читать в нём смысл не стоит. В других функциях контракт может быть иным: некоторые намеренно возвращают полезный частичный результат вместе с ошибкой (например, io.Reader.Read сообщает, сколько байт успело прочитаться до сбоя). Это соглашение о поведении конкретной функции, а не ограничение компилятора.
Почему error принято ставить последним? Читая сигнатуру слева направо, вы сначала видите «что возвращает функция при успехе», а потом — «что вернётся при сбое». Если поставить error первым, код вызова выглядел бы как err, result := f() — взгляд каждый раз спотыкается о err до того, как понял, что вообще вызывается.
Сравните (float64, bool) из предыдущего урока с (float64, error): оба паттерна используют несколько возвращаемых значений, но error добавляет к факту сбоя его описание. Вызывающий код может прочитать это описание, залогировать, передать выше — bool на такое неспособен.
