Rust 错误处理:try/catch 及其他方法——完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么Rust不使用try/catch?



在大多数编程语言(JavaScript、Python、Java)中,错误处理基于异常机制和try/catch结构。然而Rust没有采用这种方式。相反,开发者使用强大的类型系统,将错误作为函数签名的一部分。这并非偶然,而是一个经过深思熟虑的架构决策:Rust力求在编译阶段实现可预测性和安全性,消除隐藏的程序崩溃。



在本文中,我们将介绍:

  • Rust为什么放弃try/catch;
  • 主要工具如何工作:Option、Result、unwrap()、expect();
  • 什么是?运算符(问号运算符);
  • 何时使用panic!和try!宏(已弃用);
  • Rust 2024中的现代错误处理实践。


1. 基础:Option和Result——两种主要类型



Option类型:当值可能不存在时



Option<T>是一个枚举,表示要么存在一个值(Some(T)),要么没有值(None)。它非常适合那些传统意义上并非错误,但结果可能为空的情况。



fn find_user(id: u32) -> Option<String> {    let database = vec!["Alice".to_string(), "Bob".to_string()];    if id < database.len() {        Some(database[id].clone())    } else {        None    }}

fn main() { match find_user(1) { Some(name) => println!("Found: {}", name), None => println!("User not found"), }}


Result类型:成功或错误



Result<T, E>是错误处理的主要工具。它也是一个枚举:Ok(T)(成功)或Err(E)(错误)。



use std::fs::File;use std::io::Read;

fn read_file(path: &str) -> Result<String, std::io::Error> { let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents)}


2. ?运算符(问号运算符)——try/catch的替代方案



?运算符是Rust中向上传播错误的主要方式。它取代了繁琐的match结构,使代码更加简洁。如果结果是Ok,则提取值并赋给变量。如果是Err,函数将立即返回该错误。



use std::fs;use std::io;

fn copy_file(source: &str, destination: &str) -> io::Result<()> { let data = fs::read(source)?; // 如果出错——退出 fs::write(destination, &data)?; // 如果出错——退出 Ok(())}

fn main() -> io::Result<()> { copy_file("source.txt", "dest.txt")?; println!("File copied successfully"); Ok(())}


重要提示:?运算符仅适用于返回Result、Option或实现了FromResidual trait的类型。



3. panic!、unwrap和expect——当错误是致命的时候



panic!宏



panic!()会导致程序异常终止(栈展开)。它仅用于程序无法或不应该继续执行的情况:程序中的逻辑错误、不变量违反、测试等。



fn divide(a: i32, b: i32) -> i32 {    if b == 0 {        panic!("Division by zero!");    }    a / b}


unwrap()和expect()方法



unwrap()是从Option或Result中获取值的快速方法。如果它包含None或Err——它将

博客

书籍推荐