Какой стандартный интерфейс для ошибок в Go?

Ответ

В Go для ошибок существует встроенный стандартный интерфейс error:

// Встроенный интерфейс error
type error interface {
    Error() string
}

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

Создание ошибок:

  1. Простые ошибки создаются с помощью пакета errors или fmt:

    import (
        "errors"
        "fmt"
    )
    
    // C помощью errors.New
    err1 := errors.New("произошла стандартная ошибка")
    
    // C помощью fmt.Errorf для форматирования
    err2 := fmt.Errorf("ошибка пользователя %d", userID)
  2. Кастомные типы ошибок для добавления контекста:

    type MyError struct {
        StatusCode int
        Message    string
    }
    
    func (e *MyError) Error() string {
        return fmt.Sprintf("статус: %d, сообщение: %s", e.StatusCode, e.Message)
    }
    
    func doRequest() error {
        return &MyError{StatusCode: 500, Message: "внутренняя ошибка сервера"}
    }

Обработка ошибок (Go 1.13+):

С версии Go 1.13 пакет errors был расширен функциями для работы с цепочками ошибок (error wrapping):

  • errors.Unwrap(err error) error: Позволяет извлечь "внутреннюю" ошибку из обертки.
  • errors.Is(err, target error) bool: Проверяет, есть ли в цепочке ошибок err ошибка, эквивалентная target.
  • errors.As(err error, target interface{}) bool: Проверяет, есть ли в цепочке err ошибка, которую можно привести к типу target, и если да, присваивает ее target.
// Пример использования errors.As
var myErr *MyError
if err := doRequest(); errors.As(err, &myErr) {
    fmt.Printf("Получена кастомная ошибка со статусом: %dn", myErr.StatusCode)
}