我读到使用unwrap
on Result
在Rust中不是一个好习惯,并且最好使用模式匹配,因此可以适当地处理发生的任何错误.
我明白了这一点,但考虑一下读取目录的片段并打印每个条目的访问时间:
use std::fs;
use std::path::Path;
fn main() {
let path = Path::new(".");
match fs::read_dir(&path) {
Ok(entries) => {
for entry in entries {
match entry {
Ok(ent) => {
match ent.metadata() {
Ok(meta) => {
match meta.accessed() {
Ok(time) => {
println!("{:?}", time);
},
Err(_) => panic!("will be handled")
}
},
Err(_) => panic!("will be handled")
}
},
Err(_) => panic!("will be handled")
}
}
},
Err(_) => panic!("will be handled")
}
}
Run Code Online (Sandbox Code Playgroud)
我想处理上面代码中的每个可能的错误(panic
宏只是一个占位符).虽然上面的代码有效,但我觉得它很难看.处理这种情况的惯用方法是什么?
Luk*_*odt 12
我读到使用
unwrap
结果在Rust中不是一个好习惯.
那并没那么简单.例如,请在此处阅读我的答案以了解更多信息.现在来看你的主要问题:
Ok
价值传递到外部来减少右移您的代码的一个大问题是正确的转变:例如,meta.accessed()
调用缩进了很多.我们可以通过传递我们想要使用的值来避免这种情况match
:
let entries = match fs::read_dir(&path) {
Ok(entries) => entries, // "return" from match
Err(_) => panic!("will be handled"),
};
for entry in entries { // no indentation! :)
// ...
}
Run Code Online (Sandbox Code Playgroud)
这已经是使代码更具可读性的一种非常好的方法.
?
运算符将错误传递给调用函数您的函数可以返回一个Result<_, _>
类型,以便将错误传递给调用函数(是的,甚至main()
可以返回Result
).在这种情况下,您可以使用?
运算符:
use std::{fs, io};
fn main() -> io::Result<()> {
for entry in fs::read_dir(".")? {
println!("{:?}", entry?.metadata()?.accessed()?);
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
Result
对于类型,还有许多辅助方法,例如map()
或.如果你想做某事是有帮助的,如果结果是这样的东西会返回相同类型的结果.以下是您的代码和手动处理错误:and_then()
Result
and_then
Ok
and_then()
fn main() {
let path = Path::new(".");
let result = fs::read_dir(&path).and_then(|entries| {
for entry in entries {
let time = entry?.metadata()?.accessed()?;
println!("{:?}", time);
}
Ok(())
});
if let Err(e) = result {
panic!("will be handled");
}
}
Run Code Online (Sandbox Code Playgroud)
确实不仅有一种方法可以进行这种错误处理.您必须了解可以使用的所有工具,然后需要根据您的具体情况选择最佳工具.但是,在大多数情况下,?
操作员是正确的工具.