Как стать автором
Обновить
737.63
OTUS
Цифровые навыки от ведущих экспертов

Go: Управление обработкой множественных ошибок

Время на прочтение3 мин
Количество просмотров7.8K
Автор оригинала: Vincent Blanchon

Управление обработкой ошибок в Go всегда вызывает споры — это извечная тема в ежегодном опросе о самых больших проблемах, с которыми сталкиваются разработчики при работе с Go. Однако когда дело доходит до обработки ошибок в многопоточной среде или объединения нескольких ошибок одной и той же горутины, Go предоставляет отличные пакеты, которые упрощают управление обработкой множественных ошибок. Давайте посмотрим, как объединить несколько ошибок, генерируемых одной горутиной.

Одна горутина, несколько ошибок

Объединение нескольких ошибок в одну может быть весьма полезным решением, например, когда вы работаете над кодом, имеющим политику повторного запуска. Вот простой пример, в котором нам нужно группировать сгенерированные ошибки:

Эта программа считывает и анализирует CSV-текст и отображает найденную ошибку. Было бы намного удобнее группировать ошибки, чтобы получить полный отчет. Чтобы объединить ошибки в одну, у нас есть выбор между двумя отличными пакетами:

  • Используя go-multierror от HashiCorp, несколько ошибок можно объединить в одну стандартную ошибку:

Затем можно вывести отчет:

Реализация здесь аналогична, вот результат:

Ошибки объединяются через точку с запятой без какого-либо другого форматирования.

Что касается производительности каждого пакета, вот бенчмарк на той же программе, но с большим количеством ошибок:

name                    time/op         alloc/op        allocs/op
HashiCorpMultiErrors-4  6.01µs ± 1%     6.78kB ± 0%     77.0 ± 0%
UberMultiErrors-4       9.26µs ± 1%     10.3kB ± 0%      126 ± 0%

Реализация Uber немного медленнее и потребляет больше памяти. Однако этот пакет был разработан для группировки ошибок после их сбора, а не для итеративного добавления при каждом их возникновении. При группировании ошибок результаты близки, но код менее элегантен, поскольку требуется дополнительный этап. Вот обновленные результаты:

name                    time/op         alloc/op        allocs/op
HashiCorpMultiErrors-4  6.01µs ± 1%     6.78kB ± 0%     77.0 ± 0%
UberMultiErrors-4       6.02µs ± 1%     7.06kB ± 0%     77.0 ± 0%

Оба пакета используют интерфейс Go error со своей реализацией функции Error() string.

Одна ошибка, несколько горутин

Чтобы обеспечить корректность вашей программы при работе на нескольких горутинах для выполнения одной задачи, необходимо правильно управлять результатами и агрегированием ошибок.

Начнем с программы, которая использует несколько горутин для выполнения ряда действий; каждое из них длится одну секунду:

В целях демонстрации распространения ошибки, первое действие третьей горутины будет завершаться ошибкой. Вот что происходит:

Как и ожидалось, программа занимает примерно три секунды, поскольку большинству горутин необходимо выполнить три действия, каждое из которых занимает одну секунду:

go run .  0.30s user 0.19s system 14% cpu 3.274 total

Однако мы могли бы захотеть сделать горутины зависимыми друг от друга и отменять их, если одна из них даст сбой. В качестве решения, чтобы избежать ненужной работы, можно добавить контекст, чтобы, как только горутина даст сбой, она отменяла его:

Это именно то, что предоставляет errgroup; распространение ошибки и контекста при работе с группой горутин. Вот обновленный код, использующий пакет errgroup:

Теперь программы работают быстрее, поскольку они распространяют отмененный ошибкой контекст:

go run .  0.30s user 0.19s system 38% cpu 1.269 total

Преимущество пакета заключается в том, что нам больше не нужно беспокоиться о добавлении ожидающей группы и пометке горутин как выполненных. Пакет управляет этим за нас, нам просто нужно обозначить, когда мы будем готовы дождаться окончания процесса.


Перевод подготовлен в рамках набора студентов на курс "Golang Developer. Professional".

Всех желающих приглашаем на открытый вебинар «Форматирование данных». На этом demo-занятии рассмотрим:
- кодировки quoted-printable и base64;
- текстовые форматы JSON, XML и YAML;
- использование структур и интерфейсов для парсинга данных;
- сравнение бинарных сериализаторов: gob, msgpack и protobuf.
После занятия вы сможете сериализовывать и десериализовывать данные различных форматов стандартными средствами языка и сторонними библиотеками. Присоединяйтесь!

Теги:
Хабы:
+6
Комментарии0

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS