Привіт! Сьогодні я хотів би обговорити тему, яка часто трапляється в нашій повсякденній роботі, а саме - повернення та обгортання помилок, що є критично важливим аспектом розробки надійних Go-додатків з кількох причин:

<aside> 💡

Розглянемо приклад: у веб-сервісі низькорівнева помилка бази даних може бути обгорнута на рівні репозиторію, потім на рівні сервісу, і нарешті на рівні HTTP-хендлера, при цьому:

Це особливо корисно при розробці мікросервісів, де правильна обробка та логування помилок критичні для діагностики проблем у продакшені.

Стандартний пакет errors в Go підтримує об'єднання кількох помилок на додаток до більш поширеного обгортання за допомогою %w.

Я не часто бачив це використання на практиці; думаю, більшість людей або рефакторять код, щоб уникнути множинних помилок, повертають слайс []error, або використовують uber-go/multierr. Давайте розглянемо це!

var (
    ErrDatabaseConflict   = errors.New("connection refused")
    ErrCodeServiceExample = errors.New("cannot get user profile")
    ErrCodeHandlerExample = errors.New("internal error")
)

err1 := fmt.Errorf("G-switch failed: %w %w %w", ErrDatabaseConflict, ErrCodeServiceExample, ErrCodeHandlerExample)

// 2009/11/10 23:00:00 G-switch failed: connection refused cannot get user profile internal error
log.Fatal(err1)

Давайте розберемо цей код детальніше:

Це корисно, коли потрібно зберегти інформацію про декілька помилок, що сталися одночасно, і передати їх вище по стеку викликів як єдину помилку.

Другий спосіб використовує функцію errors.Join, представлену в Go 1.20. Функція приймає змінну кількість аргументів типу error, відкидає всі nil значення та об'єднує решту наданих помилок. Повідомлення форматується шляхом об'єднання рядків, отриманих викликом методу Error() кожного аргументу, розділених символом нового рядка.

err2 :=  errors.Join(
    ErrDatabaseConflict,
    ErrServiceCodeExample,
    ErrHandlerCodeExample,
)

// 2009/11/10 23:00:00 connection refused
// cannot get user profile
// internal error
log.Fatal(err2)

Як їх використовувати?

На даний момент ми розглянули два способи, якими Go підтримує обгортання помилок: пряме обгортання та об'єднані помилки.