Введение
При реальном поиске значение находится не всегда. Rust представляет такую возможность с помощью Option<T>: Some(value) означает, что значение существует, а None — что его нет. Благодаря этому отсутствие становится частью типа, а не скрывается за вымышленным числом и не приводит к панике.
Вы завершите небольшой отчёт об инвентаре. Он будет обрабатывать найденные и отсутствующие записи о запасах, различать существующую запись с нулевым количеством и отсутствие записи, а также использовать if let, когда действие требуется только для существующего значения.
Сопоставление существующих и отсутствующих значений
На этом шаге вы замените заготовленный отчёт исчерпывающим сопоставлением результата поиска, который может содержать значение или быть пустым.
Перейдите в подготовленный проект Cargo:
cd /home/labex/project/option-inventory
Откройте исходный файл:
nano src/main.rs
Подготовленная функция find_stock возвращает Option<u32>. Пока воспринимайте угловые скобки как обозначение «Option, который может содержать u32»; создание повторно используемых типов с параметрами в угловых скобках будет рассмотрено позже. Some(12) содержит количество товара на складе, а None вообще не содержит количества.
В нижней части подготовленной функции поиска _ => None использует шаблон-джокер _. Он означает «любой код, который не был сопоставлен предыдущей ветвью». Джокер не создаёт доступную переменную: он намеренно игнорирует несопоставленное значение и возвращает None.
Найдите заготовленный вызов println! внутри report и замените эту строку следующим сопоставлением:
match find_stock(code) {
Some(count) => println!("{code}: {count} in stock"),
None => println!("{code}: not found"),
}
Some(count) одновременно распознаёт существующее значение и присваивает его внутреннему числу локальное имя count. Ветка None явно обрабатывает отсутствие, поэтому сопоставление охватывает все возможные значения Option<u32>.
Сохраните файл с помощью Ctrl+O, нажмите Enter, затем выйдите с помощью Ctrl+X. Перед запуском проверьте программу:
cargo check
Сообщение Finished подтверждает, что обработаны оба варианта Option. Теперь запустите отчёт:
cargo run --quiet
Вы должны увидеть:
A1: 12 in stock
B2: 0 in stock
Z9: not found
Последняя строка создаётся для None, а первые две — для Some, включая значение Some(0).
Различение нулевого количества и отсутствия записи
На этом шаге вы зададите отдельное поведение для существующей записи с нулевым количеством, вместо того чтобы считать ноль отсутствием записи.
Some(0) и None означают разные вещи. Some(0) сообщает, что поиск нашёл запись с количеством, равным нулю. None сообщает, что записи с таким кодом нет. Поэтому подставлять, например, 0 вместо отсутствующего значения небезопасно.
Снова откройте исходный файл:
nano src/main.rs
В сопоставлении внутри report добавьте следующую ветку непосредственно перед существующей веткой Some(count):
Some(0) => println!("{code}: out of stock"),
Ветки сопоставления проверяются сверху вниз. Более конкретный шаблон Some(0) должен находиться перед Some(count), поскольку общий шаблон также соответствует нулю.
Сохраните файл и выйдите из редактора, затем запустите программу:
cargo run --quiet
Теперь вывод должен быть таким:
A1: 12 in stock
B2: out of stock
Z9: not found
Каждая строка теперь обозначает отдельное состояние: товар доступен, запись существует, но товар закончился, или запись отсутствует.
Выполнение действия только при наличии значения
На этом шаге вы используете if let для задачи, в которой действие требуется только при успешном поиске.
Исчерпывающее match удобно, когда для каждого случая требуется отдельное поведение. if let PATTERN = VALUE — это краткая условная конструкция с шаблоном для другой распространённой ситуации: выполнить один блок, если значение соответствует шаблону, и ничего не делать в противном случае.
Откройте исходный файл:
nano src/main.rs
Добавьте эту функцию непосредственно перед main:
fn highlight_available(code: &str) {
if let Some(count) = find_stock(code) {
println!("{code}: {count} available for promotion");
}
}
Шаблон успешно сопоставляется только со значением Some, поэтому count доступна внутри фигурных скобок. Блок else не нужен, потому что эта вспомогательная функция намеренно ничего не выводит для None.
В main удалите начальные // из подготовленной строки highlight_available("C3");. Сохраните файл и выйдите из редактора, затем выполните проверку и запуск:
cargo check
cargo run --quiet
Полный вывод должен быть таким:
A1: 12 in stock
B2: out of stock
Z9: not found
C3: 5 available for promotion
Четвёртая строка подтверждает, что if let извлекла значение внутри Some(5), не создавая поведения для отсутствующего значения.
Итоги
Вы сопоставили Some и None, сохранили различие между Some(0) и отсутствием записи, а также использовали if let, когда действие требовалось только для существующего значения.


