家里孩子最近在学ref="/tag/132/" style="color:#E3A3CF;font-weight:bold;">编程,写了个读取配置文件的小工具,结果一运行就崩溃。我一看代码,原来是直接打开了一个不存在的文件,程序没做任何错误处理。这种情况其实在家庭网络管理脚本里挺常见的,比如读取路由器配置、访问本地日志文件,都可能出错。这时候,Rust 的 Result 类型就派上用场了。
Result 是什么?
在 Rust 里,Result 不是异常,也不是随便返回个 null 了事。它是一个枚举类型,只有两种可能:Ok 代表成功,Err 代表失败。每个使用可能出错函数的地方,你都得面对这个现实——要么处理错误,要么程序不让你编译通过。
fn read_config() -> Result<String, std::io::Error> {
std::fs::read_to_string("config.txt")
}
上面这个函数试图读取 config.txt 文件。如果成功,返回 Ok(String);如果失败,比如文件不存在,就返回 Err(std::io::Error)。类型签名清楚告诉你:别指望一定成功。
怎么处理 Result?
最简单的办法是用 match 匹配两种情况:
match read_config() {
Ok(content) => println!("配置内容:{}", content),
Err(error) => println!("读取失败:{}", error),
}
这样程序不会崩溃,而是友好地提示哪里出了问题。适合写家庭自动化脚本时用,比如定时备份路由器设置,失败了也能记录日志而不是直接退出。
如果你不想写这么多代码,可以用 ? 操作符。它像是把“麻烦事”交给上层处理:
fn load_and_parse() -> Result<(), std::io::Error> {
let content = read_config()?;
println!("解析内容:{}", content);
Ok(())
}
? 会自动把 Err 返回出去,只在 Ok 时继续往下走。写小工具时特别顺手,既简洁又安全。
有时候你就是想快速测试,可以调用 unwrap 或 expect。但别在正式代码里用,尤其是给家人用的脚本:
let content = read_config().expect("必须找到配置文件!");
这行代码一旦文件不存在,程序就会 panic,屏幕上打出那句话。适合调试,不适合长期运行。
在家庭网络环境里,Rust 的 Result 强制你正视问题。网络请求超时、文件打不开、权限不足——这些都不是“偶尔发生”的小事,而是程序必须应对的常态。用好 Result,写出来的工具才真正可靠。