为什么这段代码不能编译?
use std::{fs, path::Path};
fn main() {
let dir = Path::new("../FileSystem");
if !dir.is_dir() {
println!("Is not a directory");
return;
}
for item in try!(fs::read_dir(dir)) {
let file = match item {
Err(e) => {
println!("Error: {}", e);
return;
}
Ok(f) => f,
};
println!("");
}
println!("Done");
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误
error[E0308]: mismatched types
--> src/main.rs:11:17
|
11 | for item in try!(fs::read_dir(dir)) {
| ^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result`
|
= note: expected type `()`
found type `std::result::Result<_, _>`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)
我也试过问号运算符:
for item in fs::read_dir(dir)? {
Run Code Online (Sandbox Code Playgroud)
哪个有不同的错误:
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:11:17
|
11 | for item in fs::read_dir(dir)? {
| ^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
Run Code Online (Sandbox Code Playgroud)
以前版本的Rust有类似的错误 std::ops::Carrier
我应该避免try!()和??处理错误的最佳方法是什么?大多数情况下,我这样做:
match error_prone {
Err(e) => {
println!("Error: {}", e);
return;
},
Ok(f) => f,
};
Run Code Online (Sandbox Code Playgroud)
但是如果我必须在for循环中使用它,那就完全是一团糟
for i in match error_prone {
// match code
} {
// loop code
}
Run Code Online (Sandbox Code Playgroud)
Vee*_*rac 44
try!是一个Err自动返回s 的宏; ?语法大致相同,但它适用于任何实现Try特征的类型.
从Rust 1.22.0开始,Option实现Try,因此可以使用?.在此之前,?只能在返回a的函数中使用Result.try!继续只与Results 一起工作.
从Rust 1.26.0开始,main允许返回一个实现的值Termination.在此之前,它不会返回任何值.
如果您标记main为返回a 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(())
}
Run Code Online (Sandbox Code Playgroud)
这是您可以将代码转换为使用的方式?:
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()),
}
}
Run Code Online (Sandbox Code Playgroud)
这里有很多错误处理,你可能没想到 - 其他语言往往不需要它!但它们存在于其他语言中 - Rust只会让你知道它.以下是错误:
Run Code Online (Sandbox Code Playgroud)entry?
迭代期间可能会发生IO错误.
Run Code Online (Sandbox Code Playgroud)path.file_name().unwrap()
并非所有路径都有文件名.我们可以unwrap这样做,因为read_dir不会给我们一个没有文件名的路径.
Run Code Online (Sandbox Code Playgroud)file_name.to_string_lossy()
你也可以to_str抛出错误,但这样做更好.存在此错误,因为并非所有文件名都是有效的Unicode.
try!并将?错误抛入返回值,将它们转换为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!"));
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
坦率地说,这个检查已经存在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()),
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7977 次 |
| 最近记录: |