问号运算符“?”
本课属于 Coddy Rust 学习旅程的“逻辑与流程”单元。第 46 课,共 66 课。
处理返回 Result 的函数时,你通常需要处理错误,可以在本地处理,也可以将错误传递给调用函数。Rust 为这种常见模式提供了一个简洁的运算符:问号运算符 ?。
? 运算符可以简洁地传递错误,无需编写冗长的 match 语句。在 Result 后面加上 ?,它会自动解包 Ok 值;如果遇到 Err,则立即从当前函数返回:
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // 如果解析失败,就返回错误
Ok(number * 2) // 如果成功,就将数字乘以 2
}这相当于编写完整的 match 语句,但简洁得多。如果 s.parse::<i32>() 返回 Ok,? 会提取其中的值,并将其赋给 number。如果返回 Err,? 会立即从整个函数中返回该错误。
注意 ::<i32> 这种语法。这称为turbofish,它会告诉 Rust 要将字符串解析成哪种类型。该函数返回 Result<i32, std::num::ParseIntError>,其中 i32 是成功时的类型,std::num::ParseIntError 是解析失败时返回的错误类型。
? 运算符只能用于返回 Result(或 Option)的函数,因为它需要能够返回错误。
挑战
简单你会收到两个输入。第一个输入是一个应解析为整数的字符串,第二个输入是另一个同样应解析为整数的字符串。创建一个名为 add_numbers 的函数,它接受两个字符串切片作为参数,并返回 Result<i32, std::num::ParseIntError>。在函数中,使用 ? 运算符解析两个字符串,并将它们的和包装在 Ok 中返回。使用这两个输入调用该函数,并通过 match 处理结果。
要求:
- 读取第一个输入(第一个数字的字符串),并去除首尾空白
- 读取第二个输入(第二个数字的字符串),并去除首尾空白
- 创建一个
add_numbers函数,它接受两个&str参数,并返回Result<i32, std::num::ParseIntError> - 在函数中,使用
?运算符将第一个字符串解析为i32 - 使用
?运算符将第二个字符串解析为i32 - 返回
Ok(sum),其中 sum 是两个解析后数字的和 - 使用这两个输入字符串调用该函数
- 使用
match表达式处理Result - 在
Ok(value)分支中,打印:Sum: [value] - 在
Err(_)分支中,打印:Parsing error
输入:
- 第一行:表示一个数字的字符串(例如,
15) - 第二行:表示另一个数字的字符串(例如,
27)
输出:
- 如果两个字符串都是有效数字:
Sum: [result] - 如果任一字符串无法解析:
Parsing error
亲手试试
use std::io;
// TODO: 在这里创建 add_numbers 函数
// 它应接收两个 &str 参数,并返回 Result<i32, std::num::ParseIntError>
fn main() {
// 读取第一个输入
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let input1 = input1.trim();
// 读取第二个输入
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let input2 = input2.trim();
// TODO: 用 input1 和 input2 调用 add_numbers
// TODO: 用 match 处理 Result
// 如果是 Ok(value),打印 "Sum: [value]"
// 如果是 Err(_),打印 "Parsing error"
}这节课包含一个小测验。开始学习即可作答,并记录你的进度。
逻辑与流程中的所有课
7使用 Result 处理错误
什么是 Result?在 Result 中使用 matchis_ok() 和 is_err()快捷方法:unwrap 和 expect问号运算符“?”将字符串解析为数字回顾:安全的除法函数自己练习: Rust 在线编译器