Пакет errors реализует функции для манипулирования ошибками.
Функция New создает ошибки, единственным содержимым которых является текстовое сообщение.
Функции Unwrap, Is и As работают с ошибками, которые могут переносить другие ошибки. Ошибка переносит другую ошибку, если ее тип имеет метод
Unwrap() error
Если e.Unwrap() возвращает ненулевую ошибку w, то мы говорим, что e переносит w.
Unwrap распаковывает упакованные ошибки. Если тип его аргумента имеет метод Unwrap, он вызывает метод один раз. В противном случае возвращается nil.
Простой способ создать упакованные ошибки - вызвать fmt.Errorf и применить глагол %w к аргументу ошибки:
errors.Unwrap(fmt.Errorf("... %w ...", ..., err, ...))
возвращает err.
Is разворачивает свой первый аргумент, последовательно ища ошибку, соответствующую второму. Он сообщает, находит ли он совпадение. Это следует использовать вместо простых проверок на равенство:
if errors.Is(err, os.ErrExist)
предпочтительнее чем
if err == os.ErrExist
потому что первый преуспеет, если err обернет os.ErrExist.
As разворачивает свой первый аргумент последовательно ищет ошибку, которая может быть назначена второму аргументу, который должен быть указателем. Если это успешно, выполняется назначение и возвращает true. В противном случае возвращается false. Форма
var perr *os.PathError
if errors.As(err, &perr) {
fmt.Println(perr.Path)
}
предпочтительнее чем
if perr, ok := err.(*os.PathError); ok {
fmt.Println(perr.Path)
}
потому что первый будет успешным, если err обернет *os.PathError.
Пример использования пользовательского типа ошибки
package main
import (
"fmt"
"time"
)
// MyError это реализация error
// которая включает время и сообщение.
type MyError struct {
When time.Time
What string
}
func (e MyError) Error() string {
return fmt.Sprintf("%v: %v", e.When, e.What)
}
func oops() error {
return MyError{
time.Date(1989, 3, 15, 22, 30, 0, 0, time.UTC),
"the file system has gone away",
}
}
func main() {
if err := oops(); err != nil {
fmt.Println(err)
}
}
Вывод:
1989-03-15 22:30:00 +0000 UTC: the file system has gone away
Функция New
func New(text string) error
New возвращает ошибку, которая форматируется как заданный текст. Каждый вызов New возвращает отдельное значение ошибки, даже если текст идентичен.
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("Неожиданная ошибка")
if err != nil {
fmt.Print(err)
}
}
Вывод:
Неожиданная ошибка
Функция Errorf пакета fmt позволяет использовать функции форматирования пакета для создания описательных сообщений об ошибках.
package main
import (
"fmt"
)
func main() {
const name, id = "бублик", 117
err := fmt.Errorf("пользователь %q (id %d) не найден", name, id)
if err != nil {
fmt.Print(err)
}
}
Вывод:
пользователь "бублик" (id 117) не найден
Функция Is (с версии Go 1.13)
func Is(err, target error) bool
Is сообщает, соответствует ли target ошибке какая-либо ошибка в цепочке err.
Цепочка состоит из самой err, за которой следует последовательность ошибок, получаемых повторным вызовом Unwrap.
Считается, что ошибка соответствует цели, если она равна этой цели или если она реализует метод Is(error) bool, такой что Is(target) возвращает true.
Тип ошибки может предоставлять метод Is, поэтому его можно рассматривать как эквивалент существующей ошибки. Например, если MyError определяет
func (m MyError) Is(target error) bool { return target == os.ErrExist }
затем Is (MyError{}, os.ErrExist) возвращает значение true. syscall.Errno.Is - пример в стандартной библиотеке.
Функция As (с версии Go 1.13)
func As(err error, target interface{}) bool
As находит первую ошибку в цепочке err, которая соответствует target, и если находит, то устанавливает target равным этому значению ошибки и возвращает true. В противном случае возвращается false.
Цепочка состоит из самой err, за которой следует последовательность ошибок, получаемых повторным вызовом Unwrap.
Ошибка соответствует цели, если конкретное значение ошибки присваивается значению, на которое указывает цель, или если ошибка имеет метод As(interface{}) bool, такой что As(target) возвращает true. В последнем случае метод As отвечает за установку цели.
Тип ошибки может предоставлять метод As, поэтому его можно обрабатывать так, как если бы это был другой тип ошибки.
As паникует, если target не является ненулевым указателем ни на тип, который реализует error, ни на любой тип интерфейса.
Пример использования As
package main
import (
"errors"
"fmt"
"os"
)
func main() {
if _, err := os.Open("non-existing"); err != nil {
var pathError *os.PathError
if errors.As(err, &pathError) {
fmt.Println("Failed at path:", pathError.Path)
} else {
fmt.Println(err)
}
}
}
Вывод:
Failed at path: non-existing
Функция Unwrap
func Unwrap(err error) error
Unwrap возвращает результат вызова метода Unwrap для err, если тип err содержит метод Unwrap, возвращающий ошибку. В противном случае Unwrap возвращает nil.
Читайте также:
Комментариев нет:
Отправить комментарий