Ответ
В Go обработка ошибок — это фундаментальная часть языка, основанная на идее, что ошибки являются значениями.
Тип error
— это встроенный интерфейс, который требует реализации всего одного метода:
// Определение интерфейса error
type error interface {
Error() string
}
Любой тип, реализующий этот метод, может быть использован как ошибка. Этот подход, в отличие от механизма исключений (try/catch) в других языках, заставляет разработчика явно обрабатывать возможные сбои.
Основные идиомы и инструменты для работы с ошибками:
-
Явная обработка: Самый распространенный паттерн — возврат ошибки как последнего значения из функции и немедленная проверка на
nil
.val, err := someFunction() if err != nil { // Обрабатываем ошибку return err } // Работаем с val
-
Создание ошибок:
errors.New("сообщение об ошибке")
: Создает простую ошибку с текстовым сообщением.fmt.Errorf("ошибка с форматированием: %v", value)
: Создает ошибку с форматированным сообщением.
-
Оборачивание ошибок (Wrapping): С Go 1.13 появилась возможность оборачивать ошибки, сохраняя исходную ошибку в цепочке. Это делается с помощью директивы
%w
вfmt.Errorf
.if err != nil { return fmt.Errorf("ошибка на верхнем уровне: %w", err) }
-
Проверка и извлечение ошибок:
errors.Is(err, target)
: Проверяет, есть ли в цепочке ошибокerr
конкретная ошибкаtarget
(например,io.EOF
).errors.As(err, &target)
: Проверяет, есть ли в цепочкеerr
ошибка определенного типа, и если есть, присваивает ее переменнойtarget
.
Пример создания кастомной ошибки:
type MyError struct {
Code int
Msg string
}
func (e *MyError) Error() string {
return fmt.Sprintf("код: %d, сообщение: %s", e.Code, e.Msg)
}
func doSomething() error {
return &MyError{Code: 500, Msg: "что-то пошло не так"}
}