Я читаю документацию поFile
:
//..
let mut file = File::create("foo.txt")?;
//..
Что ?
в этой строке? Я не помню, чтобы видел его раньше в Rust Book.
Я читаю документацию поFile
:
//..
let mut file = File::create("foo.txt")?;
//..
Что ?
в этой строке? Я не помню, чтобы видел его раньше в Rust Book.
Ответы:
Как вы могли заметить, в Rust нет исключений. У него есть паники, но их функциональность ограничена (они не могут нести структурированную информацию), и их использование для обработки ошибок не рекомендуется (они предназначены для неисправимых ошибок).
В 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,
Err(e) => return Err(e),
};
// use `i`
}
Это здорово, потому что:
Однако он далеко не идеален, поскольку очень многословен. Здесь на помощь ?
приходит оператор вопросительного знака .
Вышесказанное можно переписать как:
fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = halves_if_even(i)?;
// use `i`
}
что намного короче.
То, ?
что здесь означает, эквивалентно приведенному match
выше утверждению. Вкратце: он распаковывает Result
if OK и возвращает ошибку, если нет.
Это немного волшебно, но для обработки ошибок требуется некоторая магия, чтобы сократить шаблон, и, в отличие от исключений, сразу видно, какие вызовы функций могут или не могут вызывать ошибки: те, которые украшены ?
.
Одним из примеров волшебства является то, что это также работает для Option
:
// Assume
// fn halves_if_even(i: i32) -> Option<i32>
fn do_the_thing(i: i32) -> Option<i32> {
let i = halves_if_even(i)?;
// use `i`
}
Это связано с (нестабильной) Try
чертой.
Смотрите также:
Result
или Option
.
Он предназначен для распространения ошибки для типа исправимой ошибки Result <T, E>. Это раскрывает результат и дает вам внутреннюю ценность.
Вместо того, чтобы обрабатывать случай ошибки, вы распространяете его на вызывающий код и обрабатываете только случай Ok. Преимущество в том, что он устраняет множество шаблонов и упрощает реализацию функций.
.unwrap()
который паникует в случае ошибки.