Ответ 1
Как вы могли заметить, у Руста нет исключений. У этого есть паника, но их функциональность ограничена (они не могут нести структурированную информацию), и их использование для обработки ошибок не рекомендуется (они предназначены для неустранимых ошибок).
В Rust обработка ошибок использует Result
. Типичный пример:
fn halves_if_even(i: i32) -> Result<i32, Error> {
if i % 2 == 0 { Ok(i/2) } else { Err(/* something */) }
}
fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = match halves_if_even(i) {
Ok(i) => i,
e => return e,
};
// use `i`
}
Это здорово, потому что:
- при написании кода вы не можете случайно забыть об ошибке,
- при чтении кода вы можете сразу увидеть, что существует вероятность ошибки здесь.
Это меньше идеала, однако, в том, что он очень многословный. Здесь находится оператор вопросительного знака ?
.
Вышеприведенное может быть переписано как:
fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = halves_if_even(i)?;
// use `i`
}
что намного более кратким.
Что ?
здесь эквивалентно приведенному выше выражению match
. Короче: он распаковывает Result
, если "ОК", и возвращает ошибку, если нет.
Это немного магия, но обработка ошибок требует некоторого волшебства, чтобы вырезать шаблон, и в отличие от исключений сразу видно, какие вызовы функций могут или не могут быть обнулены: те, которые украшены ?
.