Error handling 如何处理锈迹中的错误,常见的陷阱是什么?

Error handling 如何处理锈迹中的错误,常见的陷阱是什么?,error-handling,rust,Error Handling,Rust,我注意到锈病没有例外。如何处理锈迹中的错误,常见的陷阱是什么?有没有办法通过提升、捕获、重新提升和其他方式来控制流量?我发现这方面的信息不一致。Rust通常通过两种方式解决错误: 不可恢复的错误。一旦你惊慌失措,就是这样。您的程序或线程中止,因为它遇到了无法解决的问题,并且其不变量已被违反。例如,如果在UTF-8字符串中发现无效序列 可恢复错误。在某些文档中也称为失败。而不是惊慌失措,你发出一个或。在这些情况下,您可以分别选择有效值Some(T)/Ok(T),或者选择无效值None/错误(E)

我注意到锈病没有例外。如何处理锈迹中的错误,常见的陷阱是什么?有没有办法通过提升、捕获、重新提升和其他方式来控制流量?我发现这方面的信息不一致。

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

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

  • 可恢复错误。在某些文档中也称为失败。而不是惊慌失措,你发出一个或。在这些情况下,您可以分别选择有效值
    Some(T)
    /
    Ok(T)
    ,或者选择无效值
    None
    /
    错误(E)
    。通常
    None
    用作
    null
    替换,表示缺少该值


现在是最难的部分。应用程序

打开…的包装 有时处理
选项是件麻烦事,你几乎可以保证得到一个值而不是一个错误

在这些情况下,可以使用
展开
<代码>展开
部分(e)
确定(e)
转换为
e
,否则它会崩溃。“展开”是一种将可恢复错误转化为不可恢复错误的工具

if x.is_some() {
    y = x.unwrap(); // perfectly safe, you just checked x is Some
}
if
-块中,可以完全打开它,因为它永远不会死机,因为我们已经用
x检查了它是否是
Some
。is_Some()

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

操作员/
试试宏
什么是
操作符或
试试看宏?一个简短的解释是,它要么返回
Ok()
中的值,要么过早返回错误

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

macro_rules! try {
    ($e:expr) => (match $e {
        Ok(val) => val,
        Err(err) => return Err(err),
    });
}
如果您这样使用它:

let x = File::create("my_file.txt")?;
它会将其转换为:

let x = match File::create("my_file.txt") {
    Ok(val)  => val,
    Err(err) => return Err(err),
};
缺点是函数现在返回
结果

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"));
选择符 并且有一些方便的方法,允许以一种可以理解的方式链接和处理错误。方法,如
和_then
或_else
确定或
映射错误
,等等

例如,如果您的值出错,您可以使用默认值

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

这只是你能做的事情的简要介绍。有关更多说明,请查看:


如果您需要终止一些独立的执行单元(web请求、视频帧处理、GUI事件、要编译的源文件),但并非所有应用程序都完整,那么有一个函数可以调用关闭,在出现紧急情况时捕获解卷原因

let result = panic::catch_unwind(|| {
    panic!("oh no!");
});
assert!(result.is_err());
我不会授予这个闭包对任何可能超过它的变量或任何其他全局状态的写访问权


文档中还说,函数可能也无法捕捉到某种恐慌。

您有没有看过这一点:小心burntsushi reader将迭代循环转换为迭代器的练习。这就是为什么没有人提到如何提出错误?
let result = panic::catch_unwind(|| {
    panic!("oh no!");
});
assert!(result.is_err());