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");
}
这是我得到的错误
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)
我还尝试了问号运算符: br />
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`
Rust的先前版本也有与
std::ops::Carrier
类似的错误我应该避免
try!()
和?
?处理错误的最佳方法是什么?大多数情况下,我是这样做的:for item in fs::read_dir(dir)? {
但是如果我必须在
for
循环中使用它,那就太麻烦了match error_prone {
Err(e) => {
println!("Error: {}", e);
return;
},
Ok(f) => f,
};
#1 楼
try!
是自动返回Err
的宏; ?
是语法,其功能大致相同,但可与实现Try
特征的任何类型一起使用。 从Rust 1.22.0开始,
Option
实现了Try
,因此可以与?
一起使用。在此之前,?
只能用于返回Result
的函数中。 try!
继续仅与Result
一起使用。从Rust 1.26.0起,允许
main
返回实现Termination
的值。在此之前,它不会返回任何值。从Rust 1.26.0起
如果将
main
标记为返回Result
,然后在所有“成功”的情况: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(())
}
在此之前
这是将代码转换为使用
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
不会为我们提供没有文件名的路径。错误,但这样做更好。因为并非所有文件名都不是有效的Unicode,所以存在此错误。实际上,返回所有可能出错的错误的合并错误更为合理。幸运的是,read_dir
恰好是正确的类型:file_name.to_string_lossy()
但是,坦白地说,此检查已在
to_str
中,因此您实际上可以完全删除try!
: 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!"));
}
// ...
}
评论
使它适用于其他类型的错误?运算符,我需要更改为fn main()-> Result <(),Box
– rofrol
18年8月2日在13:07
#2 楼
ques_in_main RFC是最近合并的。完成后,如果将try!()
调用替换为?
运算符,则问题中的语法确实可以正常编译并按预期工作。#3 楼
从Rust 1.26开始,Rust支持main()的返回值,因此支持在定义?
返回try!()
时在main()
中使用错误检查运算符main()
(或等效的Result
宏) br /> extern crate failure;
use failure::Error;
use std::fs::File;
type Result<T> = std::result::Result<T, Error>;
fn main() -> Result<()> {
let mut _file = File::open("foo.txt")?; // does not exist; returns error
println!("the file is open!");
Ok(())
}
以上内容编译并返回文件未找到错误(假设
foo.txt
在本地路径中不存在)。#4 楼
Veedrac的回答对我也有帮助,尽管OP的问题略有不同。在阅读Rust文档时,我看到了以下片段:会得到类似的错误。如果将代码包装在处理错误的函数中,上述代码段将起作用:use std::fs::File;
use std::io::prelude::*;
let mut file = File::open("foo.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
assert_eq!(contents, "Hello, world!");
PS。我正在学习Rust,因此这些片段不适合用作Rust编码:)
评论
尝试!是自动返回Errs的宏。您不能在main中使用它,因为main不返回任何内容。Aaaahn解释了很多。.谢谢你!在这种特定情况下,我将如何处理错误?不必诉诸上述奇怪的match语法
也可以看看。通常,懒惰的方法是将代码粘贴在您从main调用的某些包装函数中,该包装函数返回Result
基本上,错误包装会引起恐慌吗?
println!(“ {}”,path.unwrap()。path()。file_name()。unwrap()。to_str()。unwrap());真? :p