From 12b8285788afa1298d13ce81050b9b361d6ab8e7 Mon Sep 17 00:00:00 2001 From: czyt Date: Wed, 25 Sep 2024 23:45:21 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=A8=E7=AC=AC=E4=B8=89=E7=AB=A0?= =?UTF-8?q?=E9=83=A8=E5=88=86=E6=BC=8F=E6=8E=89=E7=9A=84=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chapter_1/item3-transform.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/chapter_1/item3-transform.md b/src/chapter_1/item3-transform.md index 7ee677e..3be150c 100644 --- a/src/chapter_1/item3-transform.md +++ b/src/chapter_1/item3-transform.md @@ -30,9 +30,8 @@ if let Some(i) = &s.field { } ``` -然而,大多数时候,值的缺失以及相关的错误是程序员必须处理的问题。设计软件以应对失败路径是困难的,大多数情况下这是无法通过语法支持减少的固有复杂性 —— 特别是,决定如果操作失败应该发生什么。 - -在某些情况下,正确的决定是执行一种鸵鸟策略,明确不处理失败。如果使用显式的 `match` 来这样做,会显得不必要的冗长: +然而,大多数时候,程序员通常的处理方式是提供相应的else分支:缺少值( `Option::None` ),或者返回一个可能会出现相关错误( `Result::Err(e)` )。设计能够应对失败路径的软件是困难的,而且其中大部分是本质的复杂性,无论多少语法支持都无法帮助——具体来说,就是决定如果一个操作失败了应该发生什么。 +在某些情况下,正确的决定是采取“鸵鸟策略”——把我们的头埋进沙子里,明确地不去处理失败。你不能完全忽略错误分支,因为Rust要求代码必须处理`Error`枚举的两种变体,但你可以选择将失败视为致命的错误。在失败时执行一个`panic!`意味着程序会终止,但可以在成功的假设下来编写其余的代码。通过显式`match`来执行此操作会不必要地冗长: ```rust let result = std::fs::File::open("/etc/passwd"); @@ -41,10 +40,15 @@ let f = match result { Err(_e) => panic!("Failed to open /etc/passwd!"), }; ``` +`Option`和`Result`都提供了一对方法来提取它们的内部值和`panic!`如果不存在: [unwrap](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap)和[expect](https://doc.rust-lang.org/std/result/enum.Result.html#method.expect) 。后者允许个性化失败时的错误消息,但无论哪种情况,生成的代码都更短、更简单——错误处理被委托给.unwrap()后缀(但仍然存在): +```rust +let f = std::fs::File::open("/etc/passwd").unwrap(); +``` +但要明确的是:这些辅助函数仍然会引发 `panic!`,所以选择使用它们与选择直接 `panic!`([第18条])是一样的。 -尽管如此,要明确一点:这些辅助函数仍然会引发 `panic!`,所以选择使用它们与选择直接 `panic!`([第18条])是一样的。 +然而,在许多情况下,正确的错误处理是将决策推迟给其他人。这在编写库时尤其正确,因为库的代码可能会在库作者无法预见的各种不同环境中使用。为了使库更易用,优先使用 `Result` 而不是 `Option`来表示错误,即使这可能涉及不同错误类型之间的转换([第4条])。 -然而,在许多情况下,正确的错误处理决策是将决策推迟给其他人。这在编写库时尤其正确,因为库的代码可能会在库作者无法预见的各种不同环境中使用。为了使其他人的工作更容易,即使这可能涉及不同错误类型之间的转换([第4条]),也更倾向于使用 `Result` 而不是 `Option`。 +当然,这提出了一个问题:什么算作错误?在此示例中,无法打开文件肯定是一个错误,并且该错误的详细信息(没有此类文件?权限被拒绝?)可以帮助用户决定下一步要做什么。另一方面,由于切片为空而未能检索切片的first()元素并不是真正的错误,因此它在标准库中表示为Option返回类型。在两种可能性之间进行选择需要判断,但如果错误可能传达任何有用的信息,则倾向于Result 。 `Result` 也有一个 `[#must_use]` 属性,用来引导库用户朝着正确的方向前进 —— 如果使用返回的 `Result` 的代码忽略了它,编译器将生成一个警告: