尝试运算符

Runtime errors like connection-refused or file-not-found are handled with the Result type, but matching this type on every call can be cumbersome. The try-operator ? is used to return errors to the caller. It lets you turn the common

1. match some_expression {
2. Ok(value) => value,
3. Err(err) => return Err(err),
4. }

转换成更简单的命令

1. some_expression?

We can use this to simplify our error handling code:

1. use std::io::Read;
2. use std::{fs, io};

4. fn read_username(path: &str) -> Result<String, io::Error> {
5. let username_file_result = fs::File::open(path);
6. let mut username_file = match username_file_result {
7. Ok(file) => file,
8. Err(err) => return Err(err),
9. };

11. let mut username = String::new();
12. match username_file.read_to_string(&mut username) {
13. Ok(_) => Ok(username),
14. Err(err) => Err(err),
15. }
16. }

18. fn main() {
19. //fs::write("config.dat", "alice").unwrap();
20. let username = read_username("config.dat");
21. println!("username or error: {username:?}");
22. }

This slide should take about 5 minutes.

简化 read_username 函数以使用 ?。

关键点:

  • username 变量可以是 Ok(string) 或 Err(error)。
  • 可以使用 fs::write 调用来测试不同的场景:没有文件、空文件、包含用户名的文件。
  • Note that main can return a Result<(), E> as long as it implements std::process::Termination. In practice, this means that E implements Debug. The executable will print the Err variant and return a nonzero exit status on error.