0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>В Go есть два способа сообщать о проблемах:<strong>ошибки</strong>и<strong>паника</strong>.</p>
1
<p>В Go есть два способа сообщать о проблемах:<strong>ошибки</strong>и<strong>паника</strong>.</p>
2
<h2>Ошибки vs исключения</h2>
2
<h2>Ошибки vs исключения</h2>
3
<p>Во многих языках, например, в Python или JavaScript, при возникновении ошибки выбрасывается исключение (exception), которое можно перехватить и обработать. В Go всё иначе: вместо исключений используется<strong>явная передача ошибок через возвращаемые значения</strong>.</p>
3
<p>Во многих языках, например, в Python или JavaScript, при возникновении ошибки выбрасывается исключение (exception), которое можно перехватить и обработать. В Go всё иначе: вместо исключений используется<strong>явная передача ошибок через возвращаемые значения</strong>.</p>
4
<p>Такой подход делает поток исполнения более прозрачным: вы всегда видите, где может произойти ошибка и как она обрабатывается. Цена за это - постоянные проверки при вызове функций, которые могут вернуть ошибку.</p>
4
<p>Такой подход делает поток исполнения более прозрачным: вы всегда видите, где может произойти ошибка и как она обрабатывается. Цена за это - постоянные проверки при вызове функций, которые могут вернуть ошибку.</p>
5
<h2>Паника - это ошибки программиста</h2>
5
<h2>Паника - это ошибки программиста</h2>
6
<p>Go предоставляет механизм<strong>паники (panic)</strong>, но он используется редко. Паника означает, что программа не может продолжать выполнение. Это обычно связано с<strong>ошибками в логике программы</strong>: выход за границы массива, обращение к nil, нарушение внутренних инвариантов.</p>
6
<p>Go предоставляет механизм<strong>паники (panic)</strong>, но он используется редко. Паника означает, что программа не может продолжать выполнение. Это обычно связано с<strong>ошибками в логике программы</strong>: выход за границы массива, обращение к nil, нарушение внутренних инвариантов.</p>
7
<p>Пример паники:</p>
7
<p>Пример паники:</p>
8
<p>Панику можно вызвать явно с помощью функции panic(). Обычно это делается, когда программа сталкивается с ситуацией, которая не должна происходить при корректной логике, и продолжать выполнение небезопасно:</p>
8
<p>Панику можно вызвать явно с помощью функции panic(). Обычно это делается, когда программа сталкивается с ситуацией, которая не должна происходить при корректной логике, и продолжать выполнение небезопасно:</p>
9
<p>Паника в Go приводит к аварийному завершению программы: выполнение прерывается, и если не задействован специальный механизм для её обработки, программа прекращает работу и выводит сообщение об ошибке вместе со стек-трейсом.</p>
9
<p>Паника в Go приводит к аварийному завершению программы: выполнение прерывается, и если не задействован специальный механизм для её обработки, программа прекращает работу и выводит сообщение об ошибке вместе со стек-трейсом.</p>
10
<h2>Обработка ошибок</h2>
10
<h2>Обработка ошибок</h2>
11
<p>В Go есть специальный тип error, который можно использовать для возврата сообщения об ошибке из функции. Это встроенный тип в стандартной библиотеке, и его удобно использовать для обработки любых проблем, которые могут возникнуть при выполнении функции.</p>
11
<p>В Go есть специальный тип error, который можно использовать для возврата сообщения об ошибке из функции. Это встроенный тип в стандартной библиотеке, и его удобно использовать для обработки любых проблем, которые могут возникнуть при выполнении функции.</p>
12
<p>Сигнатура функции, которая может вернуть ошибку, обычно выглядит так:</p>
12
<p>Сигнатура функции, которая может вернуть ошибку, обычно выглядит так:</p>
13
<p>Функция divide() ниже возвращает два значения: результат деления и ошибку. Если деление прошло успешно, ошибка равна nil. Если произошла ошибка (например, деление на ноль), вместо результата возвращается 0 и ненулевая ошибка. Вот пример безопасного деления с проверкой деления на ноль:</p>
13
<p>Функция divide() ниже возвращает два значения: результат деления и ошибку. Если деление прошло успешно, ошибка равна nil. Если произошла ошибка (например, деление на ноль), вместо результата возвращается 0 и ненулевая ошибка. Вот пример безопасного деления с проверкой деления на ноль:</p>
14
<h3>Что здесь происходит</h3>
14
<h3>Что здесь происходит</h3>
15
<ul><li>Функция divide() возвращает два значения: результат и ошибку.</li>
15
<ul><li>Функция divide() возвращает два значения: результат и ошибку.</li>
16
<li>Если делитель равен нулю, создаётся ошибка с помощью errors.New.</li>
16
<li>Если делитель равен нулю, создаётся ошибка с помощью errors.New.</li>
17
<li>В main() мы проверяем: если err не nil, значит произошла ошибка - выводим её.</li>
17
<li>В main() мы проверяем: если err не nil, значит произошла ошибка - выводим её.</li>
18
</ul><h2>Более подробное сообщение об ошибке</h2>
18
</ul><h2>Более подробное сообщение об ошибке</h2>
19
<p>Для создания более понятных сообщений можно использовать fmt.Errorf():</p>
19
<p>Для создания более понятных сообщений можно использовать fmt.Errorf():</p>
20
<h2>Пример: нормальное и ошибочное деление</h2>
20
<h2>Пример: нормальное и ошибочное деление</h2>
21
<p>Так как в Go нет исключений и нет конструкции try/catch, весь контроль за ошибками осуществляется<strong>через возврат значения типа error</strong>. Это приводит к тому, что код часто выглядит как последовательность:</p>
21
<p>Так как в Go нет исключений и нет конструкции try/catch, весь контроль за ошибками осуществляется<strong>через возврат значения типа error</strong>. Это приводит к тому, что код часто выглядит как последовательность:</p>
22
<p>Такая структура повторяется много раз подряд, что может создать матрешку из вложенных проверок. Поэтому работая с ошибками, принято их<em>выпрямлять</em>:</p>
22
<p>Такая структура повторяется много раз подряд, что может создать матрешку из вложенных проверок. Поэтому работая с ошибками, принято их<em>выпрямлять</em>:</p>
23
23