You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 08:23:33