← Назад к вопросам

Что входит в структуру Error?

3.0 Senior🔥 91 комментариев
#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Структура Error в Go

В языке Go ошибка (error) — это не исключение, а обычное значение, которое возвращается из функций как последний результат. Структура ошибки определена встроенным интерфейсом error из пакета errors. Это один из самых важных интерфейсов в Go, и его понимание критично для написания надежного кода.

Базовый интерфейс error

Стандартный интерфейс error предельно прост — он содержит всего один метод:

type error interface {
    Error() string
}

Любой тип, который реализует метод Error() string, автоматически удовлетворяет интерфейсу error. Это означает, что в Go вы можете создать свою собственную структуру ошибки, просто добавив к ней этот метод.

Стандартная реализация errorString

Пакет errors предоставляет простейшую реализацию через неэкспортируемую структуру errorString:

// В пакете errors:
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}

// Функция создания новой ошибки
func New(text string) error {
    return &errorString{text}
}

Эта реализация хранит только строку с описанием ошибки. Когда вы вызываете errors.New("что-то пошло не так"), создается экземпляр errorString.

Расширенная структура ошибок в пакете fmt

Пакет fmt добавляет свою реализацию через структуру wrapError (в более старых версиях — errorString):

// Пример из fmt (упрощенно)
type wrapError struct {
    msg string
    err error
}

func (e *wrapError) Error() string {
    return e.msg
}

func (e *wrapError) Unwrap() error {
    return e.err
}

Эта структура поддерживает обертывание ошибок (error wrapping), что появилось в Go 1.13.

Пользовательские структуры ошибок

Разработчики часто создают свои структуры ошибок для добавления дополнительной информации. Пример:

type HTTPError struct {
    Code    int
    Message string
    URL     string
}

func (e *HTTPError) Error() string {
    return fmt.Sprintf("HTTP %d: %s at %s", e.Code, e.Message, e.URL)
}

// Использование
func fetchData(url string) error {
    return &HTTPError{
        Code:    404,
        Message: "Not Found",
        URL:     url,
    }
}

Важные аспекты структуры ошибок в Go

  1. Простота интерфейса — один метод Error() string делает систему ошибок минималистичной и предсказуемой.

  2. Отсутствие стек-трейса по умолчанию — стандартные ошибки не содержат информации о месте возникновения. Для этого нужны сторонние пакеты вроде pkg/errors.

  3. Обертывание ошибок (Go 1.13+) — добавлены методы для работы с цепочками ошибок:

    • errors.Is() — проверяет, есть ли конкретная ошибка в цепочке
    • errors.As() — извлекает ошибку определенного типа из цепочки
    • fmt.Errorf() с %w — создает обернутую ошибку
// Пример обертывания
err := fmt.Errorf("сервис недоступен: %w", originalErr)
if errors.Is(err, originalErr) {
    // Это сработает
}
  1. nil как отсутствие ошибкиerror это интерфейс, и его нулевое значение nil означает отсутствие ошибки.

  2. Сравнение ошибок — до Go 1.13 ошибки сравнивались через ==, теперь рекомендуется использовать errors.Is() и errors.As().

Рекомендации по использованию

  • Для простых ошибок используйте errors.New() или fmt.Errorf() без %w
  • Для обертывания с контекстом используйте fmt.Errorf("контекст: %w", err)
  • Для ошибок с состоянием создавайте собственные типы, реализующие интерфейс error
  • Для проверки типов ошибок всегда используйте errors.Is() и errors.As() вместо приведения типов

Структура ошибок в Go отражает философию языка: простота, явность и контролируемость. В отличие от исключений в других языках, ошибки в Go — это часть сигнатуры функций, что заставляет разработчиков явно обрабатывать их, делая код более надежным и предсказуемым.