Option
и unwrap
В последнем примере мы показали, что можем вызвать сбой программы по своему желанию. Мы сказали нашей программе вызвать panic
, если мы выпьем сладкий лимонад. Но что, если ожидаем какой-то напиток, но не получаем его? Этот случай тоже плохой, так что и он должен быть обработан!
Мы могли бы сравнить значение с пустой строкой (""
) так же, как мы сделали это с лимонадом. Поскольку мы используем Rust, пусть компилятор сам укажет нам случаи, когда напитка нет.
Перечисление (enum
) из стандартной библиотеки (std
), называющееся Option<T>
, используется, когда значение может отсутствовать. Оно может находиться в одном из двух состояний:
Some(T)
: элемент типаT
найденNone
: элемент не найден
Эти случаи могут быть или явно обработаны с помощью match
, или неявно с unwrap
. Неявная обработка либо вернёт внутренний элемент, либо вызовет panic
.
Обратите внимание, что можно вручную настроить сообщение выдаваемое при панике с помощью expect, в противном случае unwrap
оставляет нам менее понятный вывод, чем явная обработка. В следующем примере явная обработка даёт более контролируемый результат, при этом сохраняется возможность паниковать, если это необходимо.
// Взрослый человек всё это видео, и может хорошо справиться с любым напитком. // Все напитки обрабатываются явно, с использованием конструкции `match`. fn give_adult(drink: Option<&str>) { // выдать взрослому напиток // Укажем что нужно делать, в каждом случае. match drink { Some("лимонад") => println!("Фи! Слишком сладко."), Some(inner) => println!("{}? Хорошо.", inner), None => println!("Нет напитка? Ну что ж."), } } // Другие будут паниковать перед тем как выпить напитки, содержащие сахар. // Все напитки обрабатываются неявно, с использованием `unwrap`. fn drink(drink: Option<&str>) { // `unwrap` возвращает `panic` когда получает на вход `None`. let inside = drink.unwrap(); if inside == "лимонад" { panic!("AAAaaaaa!!!!"); } println!("Я люблю {}ы!!!!!", inside); } fn main() { let water = Some("вода"); let lemonade = Some("лимонад"); let void = None; give_adult(water); give_adult(lemonade); give_adult(void); let coffee = Some("кофе"); let nothing = None; drink(coffee); drink(nothing); }