Skip to content

Commit

Permalink
Merge pull request #74 from czyt/main
Browse files Browse the repository at this point in the history
补全第三章部分漏掉的部分
  • Loading branch information
lispking authored Sep 25, 2024
2 parents c434461 + 12b8285 commit 73aa347
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions src/chapter_1/item3-transform.md
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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` 的代码忽略了它,编译器将生成一个警告:

Expand Down

0 comments on commit 73aa347

Please sign in to comment.