|
|
@ -46,7 +46,7 @@ error[E0308]: mismatched types
|
|
|
|
|
|
|
|
|
|
|
|
别慌,其实很简单,首先 `Result` 本身是定义在 `std::result` 中的,但是因为 `Result` 很常用,所以就被包含在了[`prelude`](../../appendix/prelude.md)中(将常用的东东提前引入到当前作用域内),因此无需手动引入 `std::result::Result`,那么返回类型可以简化为 `Result<std::fs::File,std::io::Error>`,你看看是不是很像标准的 `Result<T,E>` 枚举定义?只不过 `T` 被替换成了具体的类型 `std::fs::File`,是一个文件句柄类型,`E` 被替换成 `std::io::Error`,是一个 IO 错误类型.
|
|
|
|
别慌,其实很简单,首先 `Result` 本身是定义在 `std::result` 中的,但是因为 `Result` 很常用,所以就被包含在了[`prelude`](../../appendix/prelude.md)中(将常用的东东提前引入到当前作用域内),因此无需手动引入 `std::result::Result`,那么返回类型可以简化为 `Result<std::fs::File,std::io::Error>`,你看看是不是很像标准的 `Result<T,E>` 枚举定义?只不过 `T` 被替换成了具体的类型 `std::fs::File`,是一个文件句柄类型,`E` 被替换成 `std::io::Error`,是一个 IO 错误类型.
|
|
|
|
|
|
|
|
|
|
|
|
这个返回值类型说明 `File::open` 调用如果成功则返回一个可以进行读写的文件句柄,如果失败,则返回一个 IO 错误:文件不存在或者没有访问文件的权限等。总之 `File::open` 需要一个方式告知调用者是成功还是失败,并同时返回具体的文件句柄(成功)或错误信息(失败),万幸的是,这些信息通可以通过 `Result` 枚举提供:
|
|
|
|
这个返回值类型说明 `File::open` 调用如果成功则返回一个可以进行读写的文件句柄,如果失败,则返回一个 IO 错误:文件不存在或者没有访问文件的权限等。总之 `File::open` 需要一个方式告知调用者是成功还是失败,并同时返回具体的文件句柄(成功)或错误信息(失败),万幸的是,这些信息可以通过 `Result` 枚举提供:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|
use std::fs::File;
|
|
|
|
use std::fs::File;
|
|
|
|
|
|
|
|
|
|
|
@ -135,7 +135,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
|
|
|
可以看出,`expect` 相比 `unwrap` 能提供更精确的错误信息,在有些场景也会更加实用。
|
|
|
|
可以看出,`expect` 相比 `unwrap` 能提供更精确的错误信息,在有些场景也会更加实用。
|
|
|
|
|
|
|
|
|
|
|
|
## 传播错误
|
|
|
|
## 传播错误
|
|
|
|
咱们的程序几乎不太可能只有 `A->B` 形式的函数调用,一个设计良好的程序,一个功能涉及十几层的函数调用都有可能。而错误处理也往往不是哪里调用出错,就在哪里处理,实际应用中,大概率会把错误层层上传然后交给调用链的上游函数进行处理,、错误传播将极为常见。
|
|
|
|
咱们的程序几乎不太可能只有 `A->B` 形式的函数调用,一个设计良好的程序,一个功能涉及十几层的函数调用都有可能。而错误处理也往往不是哪里调用出错,就在哪里处理,实际应用中,大概率会把错误层层上传然后交给调用链的上游函数进行处理,错误传播将极为常见。
|
|
|
|
|
|
|
|
|
|
|
|
例如以下函数从文件中读取用户名,然后将结果进行返回:
|
|
|
|
例如以下函数从文件中读取用户名,然后将结果进行返回:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|