Rust Result 组合错误处理别急着 unwrap一、unwrap 是学习阶段的拐杖Rust 代码刚能跑时unwrap()很有诱惑力。文件读取 unwrapJSON 解析 unwrap请求响应 unwrap。短 demo 没问题但工具一旦给别人用panic 就会变成很差的体验。用户需要知道哪里错了能不能修下一步怎么做。错误处理不是把代码写复杂而是让失败可解释。见过一个真实场景同事的 CLI 工具做了 JSON 解析后直接 unwrap线上返回了非标准格式整个工具 panic 退出。用户只看到thread main panicked和一堆栈回溯完全不知道是配置格式不对还是依赖版本有问题。如果当时有结构化错误用户几秒就能定位。二、用问号传播错误flowchart TD A[读取文件] -- B[解析配置] B -- C[调用模型] C -- D[输出结果]?可以把错误交给上层处理让主流程保持清楚。初学时容易把?当万能符号任何错误都用它往上抛。实际上?能工作是因为Fromtrait 的自动转换前提是上层能接收这个错误类型。如果错误链中有类型转换缺失?就不灵了。fn load_config(path: str) - ResultConfig, AppError { let text std::fs::read_to_string(path)?; let config serde_json::from_str(text)?; Ok(config) }关键是定义好AppError不要把所有错误都变成字符串。三、错误类型要分层库代码应该返回结构化错误CLI 层再决定怎么展示。库里直接println!会让调用方失去控制。#[derive(thiserror::Error, Debug)] enum AppError { #[error(读取配置失败: {0})] Io(#[from] std::io::Error), #[error(配置格式错误: {0})] Json(#[from] serde_json::Error), }thiserror很适合应用和库内部错误如果是快速写 CLIanyhow也能降低样板代码。实战踩坑给 AI Agent 加了一个新 tool用thiserror定义了自己的错误类型但忘记给这个错误类型实现From转换。上层调用?传播时编译器报了很长的泛型错误第一眼看还以为生命周期乱了实际只是一个 tauri 没实现。四、给用户可行动的提示错误信息不要只贴底层异常。比如配置文件不存在要提示路径API Key 缺失要提示环境变量名模型返回格式错误要提示可以开启 debug 查看原文。match run() { Ok(_) {} Err(err) { eprintln!(错误: {err}); std::process::exit(1); } }还可以区分退出码。参数错误、网络失败、模型格式错误对自动化脚本来说含义不同。边界场景在 CI 流水线里用 AI CLI 做代码检查脚本根据退出码判断是否阻塞合并。之前所有错误都返回 exit code 1导致网络抖动超时和真的有代码问题无法区分。后来把网络类错误返回 2格式类返回 3脚本就能对不同情况做不同处理。最后unwrap可以留在测试或不会失败的初始化里但生产路径要谨慎。每少一个无解释 panic工具就更像一个可靠程序。调试技巧如果代码已经在 panic但没跑在 debugger 下可以设置panic abort或挂载 panic hook 把栈回溯写入日志。但前提是 panic 要少到值得看不然排查时也看不出来。还可以给错误增加上下文链。读取配置失败时底层错误可能只是No such file or directory但用户更想知道哪个配置路径不存在。anyhow::Context对 CLI 很实用。use anyhow::Context; let text std::fs::read_to_string(path) .with_context(|| format!(读取配置文件失败: {path}))?;对于库代码则要谨慎使用anyhow因为调用方可能需要匹配具体错误类型。应用层追求方便库层追求可组合这是一个常见分界。错误处理也要测试。可以给不存在的配置文件、非法 JSON、网络超时分别写测试确认错误信息和退出码符合预期。失败路径没人测真正失败时就会很粗糙。最后别忘了清理资源。错误提前返回时临时文件、锁文件、半写结果都可能留下。Result传播很方便但资源生命周期仍要设计。一个容易被忽略的场景?传播错误时已经打开的文件句柄、网络连接和临时目录不会自动关闭。可以用Droptrait 或者 RAII 封装来保证清理。比如把临时文件包装成一个在drop时自动删除的类型这样无论函数正常返回还是提前出错了临时资源都会释放干净。五、总结RustResult组合要用?传播错误用错误类型表达原因在 CLI 层给用户可行动提示。错误处理别急着unwrap。失败能被理解程序才算成熟。