Spec-Zone.ru › Go

Пакет errors

  • import "errors"
  • Обзор
  • Указатель
  • Примеры

Обзор

Пакет errors реализует функции для работы с ошибками.

Функция New создаёт ошибки, содержимое которых ограничивается текстовым сообщением.

Ошибка e оборачивает другую ошибку, если тип e содержит один из методов

Unwrap() error
Unwrap() []error

Если e.Unwrap() возвращает ненулевую ошибку w или срез, содержащий w, то говорят, что e оборачивает w. Возврат nil из e.Unwrap() означает, что e не оборачивает ни одной ошибки. Метод Unwrap не должен возвращать []error, содержащий значение nil.

Простой способ создавать обёрнутые ошибки — вызвать fmt.Errorf и применить глагол %w к аргументу-ошибке:

wrapsErr := fmt.Errorf("... %w ...", ..., err, ...)

Последовательное раскрытие обёрток ошибки образует дерево. Функции Is и As исследуют дерево ошибки: сначала проверяют саму ошибку, а затем по очереди дерево каждого её дочернего элемента (обход в глубину, сначала корень).

Подробнее о принципах оборачивания ошибок и о том, когда следует создавать обёртки, см. https://go.dev/blog/go1.13-errors.

Функция Is исследует дерево первого аргумента в поисках ошибки, соответствующей второму аргументу. Она сообщает, найдено ли совпадение. Её следует использовать вместо простых проверок на равенство:

if errors.Is(err, fs.ErrExist)

предпочтительнее, чем

if err == fs.ErrExist

поскольку первый вариант сработает, если err оборачивает io/fs.ErrExist.

Функция AsType исследует дерево аргумента в поисках ошибки, тип которой соответствует аргументу типа. При успехе она возвращает соответствующее значение этого типа и true. В противном случае она возвращает нулевое значение этого типа и false. Форма

if perr, ok := errors.AsType[*fs.PathError](err); ok {
	fmt.Println(perr.Path)
}

предпочтительнее, чем

if perr, ok := err.(*fs.PathError); ok {
	fmt.Println(perr.Path)
}

поскольку первый вариант сработает, если err оборачивает *io/fs.PathError.

Пример

Код:

if err := oops(); err != nil {
    fmt.Println(err)
}

Вывод:

1989-03-15 22:30:00 +0000 UTC: the file system has gone away

Указатель

  • Переменные
  • func As(err error, target any) bool
  • func AsType[E error](err error) (E, bool)
  • func Is(err, target error) bool
  • func Join(errs ...error) error
  • func New(text string) error
  • func Unwrap(err error) error

Примеры

Пакет
As
AsType
Is
Join
New
New (Errorf)
New (Unique)
Unwrap

Файлы пакета

errors.go join.go wrap.go

Переменные

ErrUnsupported указывает на то, что запрошенную операцию нельзя выполнить, поскольку она не поддерживается. Например, вызов os.Link в файловой системе, не поддерживающей жёсткие ссылки.

Функции и методы не должны возвращать эту ошибку; вместо этого им следует возвращать ошибку с соответствующим контекстом, которая удовлетворяет

errors.Is(err, errors.ErrUnsupported)

либо путём непосредственного оборачивания ErrUnsupported, либо путём реализации метода Is.

Функции и методы должны описывать случаи, в которых будет возвращена ошибка, оборачивающая эту.

var ErrUnsupported = New("unsupported operation")

func As 1.13

func As(err error, target any) bool

As находит первую ошибку в дереве err, соответствующую target, и, если такая найдена, присваивает target значение этой ошибки и возвращает true. В противном случае возвращает false.

В большинстве случаев предпочтительнее использовать AsType. As эквивалентна AsType, но устанавливает аргумент target вместо возврата соответствующей ошибки и не требует, чтобы аргумент target реализовывал error.

Дерево состоит из самой err и ошибок, полученных последовательными вызовами её метода Unwrap() error или Unwrap() []error. Если err оборачивает несколько ошибок, As исследует err, а затем её дочерние элементы с помощью обхода в глубину.

Ошибка соответствует target, если её конкретное значение можно присвоить значению, на которое указывает target, или если у ошибки есть метод As(any) bool, для которого As(target) возвращает true. Во втором случае метод As отвечает за установку target.

Тип ошибки может предоставлять метод As, чтобы с ним можно было работать как с другим типом ошибки.

As вызывает панику, если target не является ненулевым указателем на тип, реализующий error, или на тип интерфейса.

Пример

Код:

if _, err := os.Open("non-existing"); err != nil {
    var pathError *fs.PathError
    if errors.As(err, &pathError) {
        fmt.Println("Failed at path:", pathError.Path)
    } else {
        fmt.Println(err)
    }
}

Вывод:

Failed at path: non-existing

func AsType 1.26

func AsType[E error](err error) (E, bool)

AsType находит первую ошибку в дереве err, соответствующую типу E, и, если такая найдена, возвращает значение этой ошибки и true. В противном случае возвращает нулевое значение E и false.

Дерево состоит из самой err и ошибок, полученных последовательными вызовами её метода Unwrap() error или Unwrap() []error. Если err оборачивает несколько ошибок, AsType исследует err, а затем её дочерние элементы с помощью обхода в глубину.

Ошибка err соответствует типу E, если выполняется утверждение типа err.(E) или если у ошибки есть метод As(any) bool, для которого err.As(target) возвращает true, когда target является ненулевым *E. Во втором случае метод As отвечает за установку target.

Пример

Код:

if _, err := os.Open("non-existing"); err != nil {
    if pathError, ok := errors.AsType[*fs.PathError](err); ok {
        fmt.Println("Failed at path:", pathError.Path)
    } else {
        fmt.Println(err)
    }
}

Вывод:

Failed at path: non-existing

func Is 1.13

func Is(err, target error) bool

Is сообщает, соответствует ли target какая-либо ошибка в дереве err. Target должен быть сравнимым.

Дерево состоит из самой err и ошибок, полученных последовательными вызовами её метода Unwrap() error или Unwrap() []error. Если err оборачивает несколько ошибок, Is исследует err, а затем её дочерние элементы с помощью обхода в глубину.

Ошибка считается соответствующей target, если она равна target или реализует метод Is(error) bool, для которого Is(target) возвращает true.

Тип ошибки может предоставлять метод Is, чтобы его можно было считать эквивалентным существующей ошибке. Например, если MyError определяет

func (m MyError) Is(target error) bool { return target == fs.ErrExist }

то Is(MyError{}, fs.ErrExist) возвращает true. Пример в стандартной библиотеке см. в syscall.Errno.Is. Метод Is должен только поверхностно сравнивать err и target и не должен вызывать Unwrap ни для одного из них.

Пример

Код:

if _, err := os.Open("non-existing"); err != nil {
    if errors.Is(err, fs.ErrNotExist) {
        fmt.Println("file does not exist")
    } else {
        fmt.Println(err)
    }
}

Вывод:

file does not exist

func Join 1.20

func Join(errs ...error) error

Join возвращает ошибку, оборачивающую переданные ошибки. Значения ошибок nil отбрасываются. Join возвращает nil, если все значения в errs равны nil. Строковое представление ошибки — это объединение строк, полученных вызовом метода Error для каждого элемента errs, с символом новой строки между строками.

Ненулевая ошибка, возвращённая Join, реализует метод Unwrap() []error. Ошибки можно исследовать с помощью Is и As.

Пример

Код:

err1 := errors.New("err1")
err2 := errors.New("err2")
err := errors.Join(err1, err2)
fmt.Println(err)
if errors.Is(err, err1) {
    fmt.Println("err is err1")
}
if errors.Is(err, err2) {
    fmt.Println("err is err2")
}
fmt.Println(err.(interface{ Unwrap() []error }).Unwrap())

Вывод:

err1
err2
err is err1
err is err2
[err1 err2]

func New

func New(text string) error

New возвращает ошибку, строковое представление которой соответствует заданному тексту. Каждый вызов New возвращает отдельное значение ошибки, даже если текст совпадает.

Пример

Код:

err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
    fmt.Print(err)
}

Вывод:

emit macho dwarf: elf header corrupted

Пример (Errorf)

Функция Errorf пакета fmt позволяет использовать средства форматирования пакета для создания информативных сообщений об ошибках.

Код:

const name, id = "bimmler", 17
err := fmt.Errorf("user %q (id %d) not found", name, id)
if err != nil {
    fmt.Print(err)
}

Вывод:

user "bimmler" (id 17) not found

Пример (Unique)

Каждый вызов [errors.New] возвращает уникальный экземпляр ошибки, даже если аргументы совпадают. Чтобы сопоставлять ошибки, созданные с помощью [errors.New], объявите ошибку-маркер и используйте её повторно.

Код:

err1 := OopsNew()
err2 := OopsNew()
fmt.Println("Errors using distinct errors.New calls:")
fmt.Printf("Is(%q, %q) = %v\n", err1, err2, errors.Is(err1, err2))

err3 := OopsSentinel()
err4 := OopsSentinel()
fmt.Println()
fmt.Println("Errors using a sentinel error:")
fmt.Printf("Is(%q, %q) = %v\n", err3, err4, errors.Is(err3, err4))

Вывод:

Errors using distinct errors.New calls:
Is("an error", "an error") = false

Errors using a sentinel error:
Is("an error", "an error") = true

func Unwrap 1.13

func Unwrap(err error) error

Unwrap возвращает результат вызова метода Unwrap для err, если тип err содержит метод Unwrap, возвращающий error. В противном случае Unwrap возвращает nil.

Unwrap вызывает только метод вида "Unwrap() error". В частности, Unwrap не раскрывает обёртки ошибок, возвращённых функцией Join.

Пример

Код:

err1 := errors.New("error1")
err2 := fmt.Errorf("error2: [%w]", err1)
fmt.Println(err2)
fmt.Println(errors.Unwrap(err2))

Вывод:

error2: [error1]
error1

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/errors/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API