如何使用Rust示例中的目录遍历代码?回调参数cb传递方法
解决Rust目录遍历函数的回调参数传递问题
你的代码里,visit_dirs的第二个参数cb是&dyn Fn(&DirEntry)类型——这是一个指向接收&DirEntry参数的函数/闭包的 trait 对象引用。以下是几种传递这个参数的具体方法:
方式1:定义匿名闭包作为回调
直接在main里写一个匿名闭包,实现你需要的回调逻辑(比如打印文件路径):
use std::io; use std::fs::{self, DirEntry}; use std::path::Path; // 原目录遍历函数保持不变 fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> { if dir.is_dir() { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if path.is_dir() { visit_dirs(&path, cb)?; } else { cb(&entry); } } } Ok(()) } fn main() { let path = Path::new("/Users/aaron/Downloads"); // 定义回调闭包,打印每个文件的路径 let cb = |entry: &DirEntry| { println!("找到文件: {}", entry.path().display()); }; // 传递闭包的引用给visit_dirs,并处理可能的IO错误 if let Err(e) = visit_dirs(path, &cb) { eprintln!("遍历目录出错: {}", e); } }
方式2:使用命名函数作为回调
如果回调逻辑需要复用,可以单独定义一个命名函数,再传递它的引用:
use std::io; use std::fs::{self, DirEntry}; use std::path::Path; fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> { // 函数实现不变 if dir.is_dir() { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if path.is_dir() { visit_dirs(&path, cb)?; } else { cb(&entry); } } } Ok(()) } // 定义命名回调函数 fn log_file_entry(entry: &DirEntry) { println!("文件路径: {}", entry.path().display()); } fn main() { let path = Path::new("/Users/aaron/Downloads"); // 传递命名函数的引用 if let Err(e) = visit_dirs(path, &log_file_entry) { eprintln!("遍历出错: {}", e); } }
方式3:内联闭包简化写法
可以直接把闭包写在visit_dirs的调用参数里,更简洁:
fn main() { let path = Path::new("/Users/aaron/Downloads"); // 内联闭包作为回调参数 visit_dirs(path, &|entry| { println!("文件: {}", entry.path().display()); }).unwrap_or_else(|e| eprintln!("错误: {}", e)); }
额外说明
如果你的回调需要修改外部变量(比如统计文件数量),需要把visit_dirs的参数类型改成&mut dyn FnMut(&DirEntry),同时传递可变引用的闭包。例如:
fn visit_dirs(dir: &Path, cb: &mut dyn FnMut(&DirEntry)) -> io::Result<()> { // 函数内部逻辑不变,只是cb的调用方式适配可变闭包 if dir.is_dir() { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if path.is_dir() { visit_dirs(&path, cb)?; } else { cb(&entry); } } } Ok(()) } fn main() { let path = Path::new("/Users/aaron/Downloads"); let mut count = 0; visit_dirs(path, &mut |_| count += 1).unwrap(); println!("共找到{}个文件", count); }
内容的提问来源于stack exchange,提问作者farhany
相关产品推荐
相关产品推荐

