如何在Rust中进行错误处理以及常见的陷阱是什么?

Vit*_*upt 14 error-handling rust

我注意到Rust没有例外.如何在Rust中进行错误处理以及常见的陷阱是什么?有没有办法通过加注,捕获,重新加注和其他东西来控制流量?我发现这方面的信息不一致.

Dan*_*ath 28

Rust通常以两种方式解决错误:

  • 不可恢复的错误.一旦你panic!,就是这样.您的程序或线程因为遇到无法解决的问题而中止,并且违反了其不变量.例如,如果您在UTF-8字符串中找到无效序列.

  • 可恢复的错误.在某些文档中也称为失败.而不是恐慌,你发出一个Option<T>Result<T, E>.在这些情况下,您可以分别选择有效值Some(T)/ Ok(T)或无效值None/ Error(E).通常None用作null替代品,表明缺少价值.


现在来了困难的部分.应用.

有时处理Option是一个痛苦的脖子,你几乎可以保证得到一个值,而不是一个错误.

在这些情况下,使用起来非常好unwrap.unwrapSome(e)Ok(e)e,否则恐慌.展开是一种将可恢复错误转变为不可恢复的工具.

if x.is_some() {
    y = x.unwrap(); // perfectly safe, you just checked x is Some
}
Run Code Online (Sandbox Code Playgroud)

内部if-阻塞它是完美的罚款解开,因为它不应该恐慌,因为我们已经检查,这是Somex.is_some().

如果您正在编写库,unwrap则不鼓励使用,因为当它发生恐慌时,用户无法处理错误.此外,未来的更新可能会更改不变量.想象一下,如果上面的例子有if x.is_some() || always_return_true().不变量会改变,unwrap可能会引起恐慌.

?运算符/ try!

什么是?运营商或try!宏?一个简短的解释是,它要么返回一个值,Ok()要么过早地返回错误.

以下是运算符或宏扩展到的简化定义:

macro_rules! try {
    ($e:expr) => (match $e {
        Ok(val) => val,
        Err(err) => return Err(err),
    });
}
Run Code Online (Sandbox Code Playgroud)

如果你这样使用它:

let x = File::create("my_file.txt")?;
Run Code Online (Sandbox Code Playgroud)
let x = try!(File::create("my_file.txt"));
Run Code Online (Sandbox Code Playgroud)

它会将其转换为:

let x = match File::create("my_file.txt") {
    Ok(val)  => val,
    Err(err) => return Err(err),
};
Run Code Online (Sandbox Code Playgroud)

缺点是您的功能现在返回Result.

组合子

OptionResult有一些方便的方法,允许以可理解的方式链接和处理错误.方法,如and,and_then,or,or_else,ok_or,map_err,等.

例如,如果您的值被拙劣,您可以使用默认值.

let x: Option<i32> = None;
let guaranteed_value = x.or(Some(3)); //it's Some(3)
Run Code Online (Sandbox Code Playgroud)

或者如果你想把你Option变成一个Result.

let x = Some("foo");
assert_eq!(x.ok_or("No value found"), Ok("foo"));

let x: Option<&str> = None;
assert_eq!(x.ok_or("No value found"), Err("No value found"));
Run Code Online (Sandbox Code Playgroud)

这只是您可以做的事情的简要描述.有关更多说明,请查看: