try!
是一个返回的宏Err
自动;?
是几乎做同样事情的语法,但它适用于实现Try https://doc.rust-lang.org/std/ops/trait.Try.html trait.
As of 生锈 1.22.0 https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1220-2017-11-22, Option
实施Try
,所以它可以与?
。在那之前,?
只能在返回 a 的函数中使用Result
. try!
继续只与Result
s.
As of 生锈 1.26.0 https://github.com/rust-lang/rust/issues/48453, main
允许返回一个实现的值Termination
。在此之前,它不会返回任何值。
从 Rust 1.26.0 开始
如果您标记,您的原始代码就可以工作main
作为返回一个Result
然后返回Ok(())
在所有“成功”案例中:
use std::{fs, io, path::Path};
fn main() -> Result<(), io::Error> {
let dir = Path::new("../FileSystem");
if !dir.is_dir() {
println!("Is not a directory");
return Ok(());
}
for item in fs::read_dir(dir)? {
let file = match item {
Err(e) => {
println!("Error: {}", e);
return Ok(());
}
Ok(f) => f,
};
println!("");
}
println!("Done");
Ok(())
}
在那之前
这就是您可以将代码转换为使用的方式?
:
use std::{error::Error, fs, path::Path};
fn print_dir_contents() -> Result<String, Box<Error>> {
let dir = Path::new("../FileSystem");
if !dir.is_dir() {
return Err(Box::from("Is not a directory!"));
}
for entry in fs::read_dir(dir)? {
let path = entry?.path();
let file_name = path.file_name().unwrap();
println!("{}", file_name.to_string_lossy());
}
Ok("Done".into())
}
fn main() {
match print_dir_contents() {
Ok(s) => println!("{}", s),
Err(e) => println!("Error: {}", e.to_string()),
}
}
这里有很多你可能意想不到的错误处理——其他语言往往不需要它!但它们也存在于其他语言中——Rust 只是让你知道而已。以下是错误:
entry?
迭代期间可能会发生 IO 错误。
path.file_name().unwrap()
并非所有路径都有文件名。我们可以unwrap
这是因为read_dir
不会给我们一个没有文件名的路径。
file_name.to_string_lossy()
你也可以to_str
并抛出一个错误,但这样做更好。存在此错误的原因是并非所有文件名都是有效的 Unicode。
try!
and ?
将错误抛出到返回值中,将其转换为Box::Error
。实际上,返回所有可能出错的事情的合并错误更为合理。幸运的是io::Error
是正确的类型:
use std::io;
// ...
fn print_dir_contents() -> Result<String, io::Error> {
// ...
if !dir.is_dir() {
return Err(io::Error::new(io::ErrorKind::Other, "Is not a directory!"));
}
// ...
}
但坦率地说,这张支票已经在fs::read_dir
,所以你实际上可以删除if !dis.is_dir
共:
use std::{fs, io, path::Path};
fn print_dir_contents() -> Result<String, io::Error> {
let dir = Path::new("../FileSystem");
for entry in fs::read_dir(dir)? {
let path = entry?.path();
let file_name = path.file_name().unwrap();
println!("{}", file_name.to_string_lossy());
}
Ok("Done".into())
}
fn main() {
match print_dir_contents() {
Ok(s) => println!("{}", s),
Err(e) => println!("Error: {}", e.to_string()),
}
}