0Pricing
Learn Rust Coding · 课时

Result 与 ? 运算符

传播错误

Result 与 ? 运算符 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

Result 类型

Result<T, E> 表示一个可能成功并得到 Ok(T),也可能失败并得到 Err(E) 的操作。它是 Rust 主要的错误处理类型。

fn main() {
    let parsed: Result<i32, _> = "42".parse::<i32>();
    println!("{:?}", parsed);
}

匹配 Result

您可以使用 match 显式处理两种结果。

fn main() {
    match "oops".parse::<i32>() {
        Ok(n) => println!("got {n}"),
        Err(e) => println!("error: {e}"),
    }
}

返回 Result

可能失败的函数会返回 Result,由调用者决定如何处理错误。

fn halve(n: i32) -> Result<i32, String> {
    if n % 2 == 0 {
        Ok(n / 2)
    } else {
        Err("odd number".to_string())
    }
}

fn main() {
    println!("{:?}", halve(10));
    println!("{:?}", halve(7));
}

? 运算符

? 运算符会解包 Ok 值,或者从函数中提前返回 Err。它可以替代冗长的匹配并返回代码。

fn double_str(s: &str) -> Result<i32, std::num::ParseIntError> {
    let n = s.parse::<i32>()?;
    Ok(n * 2)
}

fn main() {
    println!("{:?}", double_str("21"));
    println!("{:?}", double_str("x"));
}

使用 ? 链式处理

将多个可能失败的步骤与 ? 链接起来后,代码更清晰;第一个错误会使后续步骤立即停止。

fn sum_two(a: &str, b: &str) -> Result<i32, std::num::ParseIntError> {
    let x = a.parse::<i32>()?;
    let y = b.parse::<i32>()?;
    Ok(x + y)
}

fn main() {
    println!("{:?}", sum_two("3", "4"));
}

main 中的 ?

main 可以返回 Result,因此其中也能使用 ?。返回的 Err 会以非零退出代码结束程序。

fn main() -> Result<(), std::num::ParseIntError> {
    let n: i32 = "100".parse()?;
    println!("parsed {n}");
    Ok(())
}

实用的 Result 方法

实用的组合方法:

  • unwrap_or(default) ——返回值或备用值
  • map ——转换 Ok 值
  • map_err ——转换错误
  • is_ok / is_err ——检查变体
fn main() {
    let n = "x".parse::<i32>().unwrap_or(-1);
    println!("{n}");
}

将 Option 转换为 Result

使用 ok_or 将 Option 转换为 Result,这样 ? 就能传播有意义的错误。

fn first_char(s: &str) -> Result<char, String> {
    let c = s.chars().next().ok_or("empty string".to_string())?;
    Ok(c)
}

fn main() {
    println!("{:?}", first_char("hi"));
    println!("{:?}", first_char(""));
}

? 如何转换错误

当错误类型不同时,? 会调用 From::from,将错误转换为函数声明的错误类型。这使跨层进行错误处理更加便捷。

在生产代码中避免使用 unwrap

unwrap 和 expect 遇到 Err 时会引发 panic。它们适合示例和测试,但在实际代码中应优先使用 ? 或显式处理,以便错误能够恢复。

使用 and_then 链式处理

只有前一步成功时,and_then 才会运行下一步可能失败的操作,并将值继续传递下去。

fn main() {
    let result = "8"
        .parse::<i32>()
        .and_then(|n| Ok(n * 2));
    println!("{:?}", result);
}

快速检查

对一个值为 Err 的 Result 使用 ? 运算符时,会发生什么?

回顾

您已经学习了基于 Result 的错误处理:

  • Result<T, E> 表示成功或失败
  • ? 会解包 Ok,或提前返回 Err
  • ? 可用于返回 Result 的函数和 main
  • map、map_err、unwrap_or 和 ok_or 等组合器都很有帮助
  • 在生产环境中应避免使用 unwrap

常见问题解答

「Result 与 ? 运算符」课时是免费的吗?

是的 — 「Result 与 ? 运算符」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「Result 与 ? 运算符」这节课中我会学到什么?

传播错误 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「Result 与 ? 运算符」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Result 与 ? 运算符
  2. thiserror
  3. anyhow
  4. 错误转换
← 返回 Learn Rust Coding