结论:工程约定是——库代码永不 unwrap/panic,错误用 Result 传播;应用代码在"失败即无法继续"的启动路径可 expect(必须带说明);测试、示例、原型可随意 unwrap;表示"逻辑上不可能发生"时用 expect("为什么不可能") 留下证据,而不是裸 unwrap

展开:panic 在 Rust 里意味着 bug 或不可恢复状态,不是常规错误处理机制。判断标准:调用方能否合理地从错误中恢复?能,就必须返回 Resultexpectunwrap 行为相同,但消息说明"为什么这里不可能失败",是代码评审的重要线索。工程化手段:用 clippy 的 unwrap_used lint 在 CI 中禁止生产代码 unwrap;用 ok_or/map_or_else 替代 if let ... else panic!;明确二进制的 panic 策略(unwind 还是 abort)。易错点:Mutex::lock().unwrap() 传播锁中毒 panic 通常可接受,但要知道其语义;catch_unwind 只用于 FFI 边界等场景,不是通用错误处理。追问方向:什么时候 panic 是正确选择?违反编程契约(索引越界、内部不变量被破坏)时,早 panic 好过静默错误。

// 库:传播错误
pub fn load(path: &str) -> Result<Config, StoreError> { todo!() }
// 应用入口:失败即退出,但给上下文
let cfg = load("app.toml").expect("config file must exist at startup");
// CI:clippy::unwrap_used = "deny"(生产 crate)