Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Обработка ошибок
- ----------------
- ->В Go нет исключений
- ->Ошибки возвращаются в качестве последнего значения из функции
- | Ошибка закодирована как часть сигнатуры функции
- Просто определить, может ли функция завершиться с ошибкой
- | Возвращается значение nil, если ошибка не произошла
- ->Ошибки реализуют интерфейс error из стандартной библиотеки
- | Необходимо реализовать только одну функцию: Error() string
- Основы
- ------
- Пакет "errors" стандартной библиотеки может генерировать простые
- ошибки с помощью функции New()
- import "errors"
- func divide(lhs, rhs int) (int, error) {
- if rhs == 0 {
- return 0, errors.New("cannot divide by zero")//новая ошибка
- }
- else {
- return rhs / Ihs, nil }
- }
- --------------------------------------------------------
- Интерфейс Ошибок
- type error interface {
- Error() string
- }
- Реализация
- ----------
- //Структура ошибки деления
- type DivError struct { a, b int }
- //Реализация интерфейса Error
- func (d *DivError) Error() string {
- return fmt.Sprintf("Cannot divide by zero: %d / %d ", d.a, d.b)
- }
- Использование
- ===============
- func div(a, b int) (int, error) {
- if b == 0 {
- return 0, &DivError {a, b} //структура ошибки деления
- } else {
- return a / b, nil
- }
- //пытаемся разделить 9 на 0
- answerl, err := div(9, 0)
- if err != nil {
- // "Cannot divide by zero: 9 / 0"
- fmt.Printin(err)
- return
- }
- fmt.Println ("The answer is:" , answerl)
- }
- ============================================================
- Работа с ошибками
- ------------------
- errors.Is проверяет, соответствует ли ошибка конкретному значению ошибки
- (например, предопределённой sentinel-ошибке), учитывая цепочку обёрнутых ошибок.
- errors.As проверяет, можно ли привести ошибку к определённому типу, и если да -
- присваивает её переменной нужного типа.
- Подробности
- -----------
- Функция | Что проверяет | Аргумент target | Возвращает | Пример использования
- ---------------------------------------------------------------------------------------------------------------------------
- errors.Is |Совпадение ошибки с | Ошибка (error) |true, если ошибка или | Проверка с sentinel-ошибкой:
- |конкретным значением | |обёрнутая ошибка равна | errors.Is(err, ErrNotFound)
- | | |target |
- ---------------------------------------------------------------------------------------------------------------------------
- errors.As |Принадлежность ошибки| Указатель на переменную |true, если ошибка или | Извлечение ошибки нужного
- |к конкретному типу | ошибки нужного типа |обёрнутая ошибка | типа: errors.As(err, &myErr)
- | | (например, *MyError) |приводится к типу |
- -----------------------------------------------------------------------------------------------------------------------------
- Пример с errors.Is
- var ErrNotFound = errors.New("not found")
- if errors.Is(err, ErrNotFound) {
- fmt.Println("Ошибка: не найдено")
- }
- errors.Is вернёт true, если err или любая ошибка в цепочке обёрток равна ErrNotFound.
- Пример с errors.As
- type MyError struct {
- Code int
- }
- var myErr *MyError
- if errors.As(err, &myErr) {
- fmt.Printf("Ошибка типа MyError с кодом %d\n", myErr.Code)
- }
- errors.As проверит, есть ли в цепочке ошибок ошибка типа *MyError, и если да - присвоит её переменной myErr.
- Когда использовать
- Используйте errors.Is, когда хотите проверить, равна ли ошибка конкретному значению (например, sentinel-ошибке).
- Используйте errors.As, когда хотите проверить, принадлежит ли ошибка определённому типу, и получить доступ к её полям.
- Итог
- errors.Is - для сравнения с конкретной ошибкой (значением).
- errors.As - для проверки и извлечения ошибки по типу.
- Обе функции рекурсивно обходят цепочку обёрнутых ошибок, что позволяет работать с комплексными ошибками, обогащёнными контекстом.
- //определяем структуру ошибки
- type UserError struct {
- Msg string
- }
- //определяем для нее Error
- func (u *UserError) Error() string {
- return fmt Sprintf( User error: %v string(u.Msg))
- }
- //выполняем какую-то функцию
- _, err := someFunc( sample")
- if err != nil
- {
- var InputError = UserError{"Input Error"}
- if errors.Is(err, &InputError)
- {
- fmt.Printin("Input error:", err)
- } else {
- fmt.Println(’Other error:", err)
- }
- }
- //выполняем какую-то функцию
- _, err := someFunc( sample")
- if err != nil
- {
- var this_error = UserError *
- //Если err имеет тип UserError
- if errors.As(err, this_error)
- {
- fmt.Printin("Input error:", err)
- } else {
- fmt.Println(’Other error:", err)
- }
- }
- func main() {
- // Создаём ошибку типа *UserError
- use := &UserError{Msg: "ERROR"}
- // Объявляем переменную для поиска ошибки типа *UserError1
- var ue *UserError1
- // Пробуем привести ошибку use к типу *UserError1
- if errors.As(use, &ue) {
- fmt.Println("The Same AS")
- } else {
- fmt.Println("Not The Same AS")
- }
- // Пример с ошибкой того же типа
- var ue2 *UserError
- if errors.As(use, &ue2) {
- fmt.Println("This is UserError:", ue2.Msg)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement