У цій статті я продемонструю основи обробки функцій помилок у Go і як ними користуватися.
Що таке тип помилки?
Тип помилки в Go є типом інтерфейсу.
type error interface {
Error() string
}
Таким чином, в основному, тип помилки - це все, що реалізує метод Error()
.
Створення екземпляра помилки
Існує два способи створення помилки.
- функція error.New
- функція fmt.Errorf
func bar() error {
return errors.New("error: an error occurred")
}
func foo() error {
return fmt.Errorf("error: %s", "an error occurred")
}
Кожен виклик цих двох функцій повертає відмінне значення помилки, навіть якщо текст ідентичний.
fmt.Println(foo()==bar()) # false
Визначення очікуваних помилок
Визначення очікуваних помилок є ключовою технікою в Go, оскільки вона допомагає нам виявляти конкретні помилки та по різному їх обробляти.
package main
import (
"errors"
"fmt"
)
var ErrDivideByZero = errors.New("divide by zero")
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, ErrDivideByZero
}
return a / b, nil
}
func main() {
a, b := 5, 0
result, err := Divide(a, b)
if err != nil {
switch {
case errors.Is(err, ErrDivideByZero):
fmt.Println("Divide by zero")
default:
fmt.Printf("unknown error: %v\n", err)
}
}
fmt.Printf("%d / %d = %d\n", a, b, result)
}
Ось приклад;
- Спочатку ми визначаємо сигнальну помилку під назвою
ErrDivideByZero
. - Потім ми визначаємо функцію
Divide
, яка повертає цю помилку, коли другий аргумент дорівнює нулю. - Пізніше ми використовуємо
errors.Is
, щоб перевірити, чи повернута помилка,ErrDivideByZero
і виконати певні дії.
Обгортання помилок
Обгорнути помилку, це взяти одне значення помилки та помістити його в інше значення помилки, як загорнутий подарунок.
Це корисно, коли ви хочете повернути конкретне повідомлення про помилку, коли виникла конкретна помилка.
Ось приклад.
package main
import (
"errors"
"fmt"
)
var ErrDivideByZero = errors.New("divide by zero")
func doDivide(a, b int) (int, error) {
result, err := Divide(a, b)
if err != nil {
return 0, fmt.Errorf("divide error: %w", err)
}
return result, nil
}
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, ErrDivideByZero
}
return a / b, nil
}
func main() {
a, b := 5, 0
result, err := doDivide(a, b)
if err != nil {
switch {
case errors.Is(err, ErrDivideByZero):
fmt.Println("Divide by zero")
default:
fmt.Printf("unknown error: %v\n", err)
}
}
fmt.Printf("%d / %d = %d\n", a, b, result)
}
- По-перше, функція
Divide
повертаєErrDivideByZero
коли другий аргумент дорівнює нулю - Потім, функція
doDivide
обгортає помилкуErrDivideByZero
спеціальним повідомленням про помилку та повертає нову помилку. - Нарешті, в основній функції ми використовуємо функцію
errors.Is
, щоб перевірити, чи є всередині обгорнутого ланцюга тип помилкиErrDivideByZero
.
Висновок
Ось три виноси
- Тип помилки в Go є типом інтерфейсу.
- Попередньо визначені помилки дозволять нам перевірити, яка помилка сталася пізніше.
- Обгонуті помилки додають контекст до викликів функцій (подібно до трасування стека)
Ще немає коментарів