为什么 fs::read_dir() 在 Result<DirEntry, Error> 上返回迭代器

sag*_*aga 1 error-handling rust

这段代码Ok在我的系统上打印了几个s:

use std::fs;

fn main() {
    fs::read_dir("/home").unwrap().for_each(|e| {
        println!("{:?}", e);
    });
}
Run Code Online (Sandbox Code Playgroud)

我需要unwrapDirEntry使用前元素。

国家的文件fs::read_dir

返回目录中条目的迭代器。

迭代器将产生 的实例io::Result<DirEntry>。在最初构造迭代器后可能会遇到新的错误。

文档在谈论什么样的错误?它是安全unwrapResult

Frx*_*rem 5

fs::read_dir打开目录时可能会遇到错误,例如目录不存在或用户没有读取权限。但是,即使在打开目录后,也可能出现任意数量的错误:

  • 该目录可能已被删除;
  • 目录的权限可能已更改;
  • 底层存储介质可能有 IO 错误(例如硬盘驱动器故障);
  • 该目录可能位于已删除的可移动驱动器(或已断开连接的网络驱动器)上;
  • 或操作系统可能为操作提供的任何其他错误

不可能在给出的结果中返回此错误fs::read_dir;相反,我们必须在迭代器本身中提供它们。这就是迭代器产生 type 项的原因Result<DirEntry, std::io::Error>,这样程序员就有可能捕捉和处理这些错误。


至于unwrap结果是否安全,只有当您确定结果不是错误时才真正安全(否则您的代码会恐慌)。在许多情况下,例如在原型设计时,您可能并不关心您的代码是否会崩溃,但是在用 Rust 编写正确的应用程序时,您应该避免unwrap并依赖正确的错误处理和错误传播。

这是我在使用可能会产生错误的迭代器时通常使用的模式:

use std::{fs, io};

fn read_dir_and_do_stuff() -> Result<(), io::Error> {
    for entry in fs::read_dir("/home")? {
        //                            ^
        //               v------------'---  automatically return errors
        let entry = entry?;

        // ... do something
        println!("{:?}", entry);
    }

    Ok(())
}

fn main() {
    if let Err(err) = read_dir_and_do_stuff() {
         // handle error
         println!("Error occurred: {}", err);
         return;
    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用方法,如Iterator::try_foldIterator::try_for_eachIterator::collect::<Result<..., E>>如果你想用链接代替for in