Пакет errors
Обзор
Пакет errors реализует функции для работы с ошибками.
Функция New создаёт ошибки, содержимым которых является только текстовое сообщение.
Ошибка e оборачивает другую ошибку, если тип e имеет один из методов
Unwrap() error Unwrap() []error
Если e.Unwrap() возвращает не nil ошибку w или срез, содержащий w, то мы говорим, что e оборачивает w. Возвращение nil ошибки из e.Unwrap() указывает, что e не оборачивает никакую ошибку. Недопустимо, чтобы метод Unwrap возвращал []error, содержащий значение nil.
Простой способ создать оборачивающую ошибку — вызвать fmt.Errorf и применить к аргументу ошибки %w:
wrapsErr := fmt.Errorf("... %w ...", ..., err, ...)
Последовательное распаковку ошибки создаёт дерево. Функции Is и As проверяют дерево ошибки, сначала проверяя саму ошибку, а затем дерево каждого из её дочерних элементов по очереди (обход в глубину по принципу «префикс»).
Функция Is проверяет дерево своего первого аргумента, ища ошибку, соответствующую второму. Она сообщает, найдена ли такая ошибка. Её следует использовать вместо простых проверок на равенство:
if errors.Is(err, fs.ErrExist)
предпочтительнее
if err == fs.ErrExist
потому что в первом случае будет успех, если err оборачивает io/fs.ErrExist.
Функция As проверяет дерево своего первого аргумента, ища ошибку, которую можно присвоить своему второму аргументу, который должен быть указателем. Если поиск успешен, то выполняется присваивание и возвращается true. В противном случае возвращается false. Форма
var perr *fs.PathError
if errors.As(err, &perr) {
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
Индекс
Файлы пакета
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.
Дерево состоит из самой 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 Is 1.13
func Is(err, target error) bool
Is сообщает, соответствует ли какая-либо ошибка в дереве 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.
Пример
Код:
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")
}
Вывод:
err1 err2 err is err1 err is 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
func Unwrap 1.13
func Unwrap(err error) error
Unwrap возвращает результат вызова метода Unwrap на err, если тип err содержит метод Unwrap, возвращающий ошибку. В противном случае 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/