Основы Go
Теория: Ошибки
В Go есть два способа сообщать о проблемах: ошибки и паника.
Ошибки vs исключения
Во многих языках, например, в Python или JavaScript, при возникновении ошибки выбрасывается исключение (exception), которое можно перехватить и обработать. В Go всё иначе: вместо исключений используется явная передача ошибок через возвращаемые значения.
Такой подход делает поток исполнения более прозрачным: вы всегда видите, где может произойти ошибка и как она обрабатывается. Цена за это - постоянные проверки при вызове функций, которые могут вернуть ошибку.
Паника — это ошибки программиста
Go предоставляет механизм паники (panic), но он используется редко. Паника означает, что программа не может продолжать выполнение. Это обычно связано с ошибками в логике программы: выход за границы массива, обращение к nil, нарушение внутренних инвариантов.
Пример паники:
Панику можно вызвать явно с помощью функции panic(). Обычно это делается, когда программа сталкивается с ситуацией, которая не должна происходить при корректной логике, и продолжать выполнение небезопасно:
Паника в Go приводит к аварийному завершению программы: выполнение прерывается, и если не задействован специальный механизм для её обработки, программа прекращает работу и выводит сообщение об ошибке вместе со стек-трейсом.
Обработка ошибок
В Go есть специальный тип error, который можно использовать для возврата сообщения об ошибке из функции. Это встроенный тип в стандартной библиотеке, и его удобно использовать для обработки любых проблем, которые могут возникнуть при выполнении функции.
Сигнатура функции, которая может вернуть ошибку, обычно выглядит так:
Функция divide() ниже возвращает два значения: результат деления и ошибку. Если деление прошло успешно, ошибка равна nil. Если произошла ошибка (например, деление на ноль), вместо результата возвращается 0 и ненулевая ошибка. Вот пример безопасного деления с проверкой деления на ноль:
Что здесь происходит
- Функция
divide()возвращает два значения: результат и ошибку. - Если делитель равен нулю, создаётся ошибка с помощью
errors.New. - В
main()мы проверяем: еслиerrнеnil, значит произошла ошибка — выводим её.
Более подробное сообщение об ошибке
Для создания более понятных сообщений можно использовать fmt.Errorf():
Пример: нормальное и ошибочное деление
Как устроены программы в Go с ошибками
Так как в Go нет исключений и нет конструкции try/catch, весь контроль за ошибками осуществляется через возврат значения типа error. Это приводит к тому, что код часто выглядит как последовательность:
Такая структура повторяется много раз подряд, что может создать матрешку из вложенных проверок. Поэтому работая с ошибками, принято их выпрямлять:
