Go с самого начала строился вокруг явного возврата ошибок вместо исключений. Это позволяет разрабатывать предсказуемый код и избегать скрытых ловушек, свойственных try/catch конструкциям других языков (например, Java или C++). Ошибка в Go — это интерфейс, реализующий метод Error(), что позволяет создавать как простые, так и составные/обёрнутые ошибки с контекстом.
Проблемы возникают при неправильной обработке ошибок (например, если их игнорировать через _ или не оборачивать дополнительной информацией для дебага) или создании "магических" ошибок, не соответствующих интерфейсу error. Важно также уметь возвращать ошибки из публичных функций и проверять их в каждом вызове.
Решение — использовать стандартные подходы:
Пример кода:
import ( "errors" "fmt" ) type NotFoundError struct { Resource string } func (e *NotFoundError) Error() string { return fmt.Sprintf("%s not found", e.Resource) } func GetUser(id int) (string, error) { if id != 1 { return "", &NotFoundError{"User"} } return "Steve", nil } func main() { user, err := GetUser(2) if err != nil { if nfe, ok := err.(*NotFoundError); ok { fmt.Println(nfe.Resource, "problem") } else { fmt.Println("error:", err) } } fmt.Println("user:", user) }
Ключевые особенности:
Можно ли при обработке error делать сравнение через ==, или нужно использовать специальные методы?
Лучше всегда использовать errors.Is() для сравнения с ошибками-обёртками, иначе сравнение через == может не сработать при наличии обёртывания ошибки.
if errors.Is(err, os.ErrNotExist) { // обработка отсутствия файла }
Обязательно ли реализовывать тип-структуру для кастомной ошибки, или достаточно использовать errors.New("...")?
Если нужен только текст ошибки, достаточно errors.New(). Если важно сохранить контекст (например, имя ресурса), лучше определить struct с методом Error().
Как правильно возвращать ошибку в случае успешного выполнения функции?
В случае успеха всегда возвращайте nil-ошибку.
return result, nil
Негативный кейс
Разработчик пишет функцию, возвращающую ошибку без пояснений (просто errors.New("fail")). При анализе логов установить причину не получается.
Плюсы:
Минусы:
Позитивный кейс
Разработчик определяет кастомный тип ошибки NotFoundError и возвращает его с подробным описанием.
Плюсы:
Минусы: