Выбрать главу

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Вывод:

1 + 2 = 3

3 + 4 = 7

(2 * 3) + 1 = 7

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

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

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

Тип Option предназначен для случаев, когда значение не обязательно или когда отсутствие значения не является ошибкой. Например, корневые директории / и C: не имеют родителя. При работе с Option, для прототипирования и случаев, когда мы точно знаем, что значение должно быть, отлично подходит unwrap. Однако более полезен expect, так как он позволяет указать сообщение об ошибке на случай, если что-то пойдёт не так.

Когда есть вероятность, что что-то пойдёт не так и вызывающая сторона должна как-то обработать эту ситуацию, используйте Result. Вы также можете использовать unwrap и expect (пожалуйста, не делайте этого, если вы не пишете тест или не прототипируете).

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

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

fn give_princess(gift: &str) {

// Принцесса ненавидит змей, поэтому нам нужно остановиться, если она не одобрит!

if gift == "змея" { panic!("AAAaaaaa!!!!"); }

println!("Я люблю тебя, {}!!!!!", gift);

}

fn main() {

give_princess("плюшевый мишка");

give_princess("змея");

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

В последнем примере мы показали, что мы по собственному желанию можем вызвать сбой программы. Мы сказали нашей программе вызвать panic, если принцессе подарят несоответствующий подарок - змею. Но что если принцесса ожидает подарок, но не получает его? Этот случай тоже плохой, так что и он должен быть обработан!

Мы можем проверить пустую строку ("") так же, как мы сделали это со змеёй. Поскольку мы используем Rust, давайте укажем компилятору случаи, когда подарка нет.

Перечисление (enum) из стандартной библиотеки (std), называющееся Option<T>, используется, когда значение может отсутствовать. Оно проявляется как одна из двух опций (options):

   • Some(T): элемент типа T найден

   • None: элемент не найден

Эти случаи могут быть явно обработаны через match или неявно с unwrap. Неявная обработка либо вернёт внутренний элемент, либо вызовет panic.

Обратите внимание, что можно вручную настроить сообщение отображаемое при вызове panic с помощью expect, но unwrap в противном случае оставляет нам менее понятный вывод, чем явная обработка. В следующем примере явная обработка при желании даёт более контролируемый результат, сохраняя при этом возможности panic.

// Простолюдин видел всё это, и может справиться с любым подарком хорошо.

// Все подарки обрабатываются с помощью `match`.

fn give_commoner(gift: Option<&str>) {

// Укажите порядок действий для каждого случая.