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
From::from
以潜在地将其转换为另一种类型。它有点神奇,但错误处理需要一些魔法来减少样板代码,与异常不同,可以立即看到哪些函数调用可能会出错:那些带有?
的函数。
魔法的一个例子是,这也适用于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`
}
?
运算符在 Rust 1.13.0 版本中得到稳定,由(不稳定的)Try
trait 支持。Result
或 Option
,那将很好。 - hellow它是一个后缀运算符,用于解包Result<T, E>
和Option<T>
值。
如果应用于Result<T, E>
,它将解包结果并给出内部值,将错误传播到调用函数。
let number = "42".parse::<i32>()?;
println!("{:?}", number); // 42
Option<T>
时,它将None
传播给调用者,留下了Some分支的内容让你处理。let val = Some(42)?;
println!("{:?}", val); // 42
?
运算符只能在返回Result
或Option
的函数中使用,用法如下:
use std::num::ParseIntError;
fn main() -> Result<(), ParseIntError> {
let number = "42".parse::<i32>()?;
println!("{:?}", number);
Ok(())
}
Rust提供的便利功能可消除样板代码,使函数实现更简单。
.unwrap()
,后者在出现错误时会引发 panic。 - Jordan它用于 传播错误
。有时,我们编写的代码可能会失败,但我们不想立即捕获和处理错误。如果您在每个地方都要处理错误,那么您的代码将变得难以阅读。相反,如果发生错误,我们可能希望让调用者来处理它。我们希望错误向上一级调用堆栈传播。
// file type is Result if "?" is not used
// file:Result<File,Error>
let mut file = File::create("foo.txt");
// file type is File if "?" is used
// file:File
let mut file = File::create("foo.txt")?;
// if an error occurs, code after this line will not be executed
// function will return the error
?
的行为取决于此函数返回的是成功结果还是错误结果:
file
。file
。错误将由函数返回给调用者。?
与此代码相同:let mut file = match File::create("foo.txt") {
Err(why) => panic!("couldn't create {}: {}", display, why),
Ok(file) => file,
};
?
在Option类型中也有类似的作用。在返回Option的函数中,你可以使用?来解包一个值,并在None的情况下提前返回:
现有的答案都很好!我想提供一个小的代码片段来演示在这个问号后面使用From::from()
的用法:
fn _parse(str: &str) -> Result<i32, &str> {
if let Ok(num) = str.parse::<i32>() {
Ok(num)
} else {
Err(str)
}
}
fn parse(str: &str) -> Result<(), String> {
let num = _parse(str)?;
println!("{}", num);
Ok(())
}
parse()
中,使用?
可以手动重写为:fn parse(str: &str) -> Result<(), String> {
match _parse(str) {
Ok(n) => {
println!("{}", n);
Ok(())
}
Err(str) => Err(<String as From<&str>>::from(str)),
}
}