且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-11-11 20:06:46

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

Rust generally solves errors in two ways:

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

  • Unrecoverable errors. Once you panic!, that's it. Your program or thread aborts because it encounters something it can't solve and its invariants have been violated. E.g. if you find invalid sequences in what should be a UTF-8 string.

可恢复的错误.在某些文档中也称为失败.你没有恐慌,而是发出一个 OptionResult代码>.在这些情况下,您可以分别选择有效值 Some(T)/Ok(T) 或无效值 None/错误(E)代码>.一般None作为null的替换,表示值缺失.

Recoverable errors. Also called failures in some documentation. Instead of panicking, you emit a Option<T> or Result<T, E>. In these cases, you have a choice between a valid value Some(T)/Ok(T) respectively or an invalid value None/Error(E). Generally None serves as a null replacement, showing that the value is missing.

现在是困难的部分.申请.

Now comes the hard part. Application.

有时处理 Option 是一件头疼的事,您几乎可以保证得到一个值而不是错误.

Sometimes dealing with an Option is a pain in the neck, and you are almost guaranteed to get a value and not an error.

在这些情况下,使用 unwrap 完全没问题.unwrapSome(e)Ok(e) 变成 e ,否则会 panic.Unwrap 是一种将可恢复错误变为不可恢复的工具.

In those cases it's perfectly fine to use unwrap. unwrap turns Some(e) and Ok(e) into e, otherwise it panics. Unwrap is a tool to turn your recoverable errors into unrecoverable.

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

if 块内,解包完全没问题,因为它永远不会恐慌,因为我们已经用 x.is_some().

Inside the if-block it's perfectly fine to unwrap since it should never panic because we've already checked that it is Some with x.is_some().

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

If you're writing a library, using unwrap is discouraged because when it panics the user cannot handle the error. Additionally, a future update may change the invariant. Imagine if the example above had if x.is_some() || always_return_true(). The invariant would changed, and unwrap could panic.

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

What's the ? operator or the try! macro? A short explanation is that it either returns the value inside an Ok() or prematurely returns error.

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

Here is a simplified definition of what the operator or macro expand to:

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

如果你像这样使用它:

let x = File::create("my_file.txt")?;

let x = try!(File::create("my_file.txt"));

它会转换成这样:

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

缺点是你的函数现在返回Result.

The downside is that your functions now return Result.

OptionResult 有一些方便的方法,允许以可理解的方式链接和处理错误.andand_thenoror_elseok_or 等方法map_err

例如,您可以有一个默认值,以防您的值被破坏.

For example, you could have a default value in case your value is botched.

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

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

Or if you want to turn your Option into a 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"));

这只是您可以做的事情的简要介绍.如需更多解释,请查看:


This is just a brief skim of things you can do. For more explanation, check out: