Rust中map函数内如何做正确的错误处理?附文件读取转整数示例
问题1:原示例属于合格的Rust代码吗?
语法层面完全合法,可以正常编译运行,是否合格取决于使用场景:
- 如果你写的是个人用的小脚本、一次性工具,能接受出错直接终止程序,那完全够用,算合格的代码。
- 如果是要发布的库、生产环境运行的程序,就不算合格:
expect会直接触发不可恢复的panic,调用方没有任何处理错误的空间,只要出现文件不存在、行读取失败、数值格式错误的情况,程序会直接崩溃退出。
问题2:是否应该采用你给出的第二种错误处理写法?
不推荐,这个写法有两个明显的问题:
- 仍然保留了
File::open和行读取阶段的expect,这两个环节出错还是会直接panic,错误处理覆盖不全。 - 解析int失败返回-1属于「哨兵值」设计,调用方无法区分返回的-1是文件真实存在的数值,还是解析错误的默认值,很容易引发隐蔽的逻辑bug,这也是Rust官方不推荐的错误处理方式。
更符合Rust惯例的写法建议
通常有两种可选方案,按需选择即可:
方案1:把错误透传给调用方处理
函数返回Result类型,所有错误都往上抛,交给调用方决定遇到错误时是终止、重试还是提示用户,这是最通用的处理方式:
use std::{ fs::File, io::{prelude::*, BufReader}, path::Path, }; fn lines_from_file(filename: impl AsRef<Path>) -> Result<Vec<i32>, Box<dyn std::error::Error>> { let file = File::open(filename)?; let buf = BufReader::new(file); let mut res = Vec::new(); for line in buf.lines() { res.push(line?.parse()?); } Ok(res) }
方案2:静默跳过错误行(仅适合不需要严格校验的场景)
如果你的业务允许忽略读取失败、解析失败的行,可以用filter_map过滤错误,注意最好配套日志记录被跳过的行,方便排查问题:
fn lines_from_file(filename: impl AsRef<Path>) -> Vec<i32> { let file = File::open(filename).expect("文件不存在"); let buf = BufReader::new(file); buf.lines() .filter_map(|l| l.ok()) .filter_map(|l| l.parse::<i32>().ok()) .collect() }
内容的提问来源于stack exchange,提问作者Skary
相关产品推荐
相关产品推荐

