为了账号安全,请及时绑定邮箱和手机立即绑定

在 GOLANG 中尽可能快地递归遍历所有文件夹中的所有文件

在 GOLANG 中尽可能快地递归遍历所有文件夹中的所有文件

Go
肥皂起泡泡 2022-11-28 10:44:11
我面临一个问题,即使在论坛上花了一天时间,我仍然无法完全理解和解决。所以在这里,我做了一个循环所有文件夹及其子文件夹的函数,它有 2 个子函数:- 对于找到的每个文件,列出文件的名称。- 对于找到的每个文件夹,重新启动相同的父函数以再次查找子文件和文件夹。为简化起见,该宏以递归方式列出了树中的所有文件。但我的目标是尽可能快地完成,所以每次遇到新文件夹时我都会运行一个新的 goroutine。问题:我的问题是,当树结构太大(文件夹和子文件夹中的文件夹太多......)时,脚本会生成太多线程,因此会出现错误。所以我增加了这个限制,但突然间它不再需要电脑了:/所以我的问题是,如何制作适合我的代码的工作系统(带池大小)?不管我怎么看,我都没有看到如何说,例如,生成新的 goroutines 达到一定的限制,清空缓冲区的时间。源代码:https ://github.com/LaM0uette/FilesDIR/tree/V0.5主要的:package mainimport (    "FilesDIR/globals"    "FilesDIR/task"    "fmt"    "log"    "runtime/debug"    "sync"    "time")func main() {    timeStart := time.Now()    debug.SetMaxThreads(5 * 1000)    var wg sync.WaitGroup    // task.DrawStart()    /*        err := task.LoopDir(globals.SrcPath)        if err != nil {            log.Print(err.Error())        }    */    err := task.LoopDirsFiles(globals.SrcPath, &wg) // globals.SrcPath = My path with ~2000000 files ( this is a serveur of my entreprise)    if err != nil {        log.Print(err.Error())    }    wg.Wait()    fmt.Println("FINI: Nb Fichiers: ", task.Id)    timeEnd := time.Since(timeStart)    fmt.Println(timeEnd)}
查看完整描述

1 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

如果您不想使用任何外部包,您可以创建一个单独的工作程序来处理文件,然后启动任意数量的工作程序。之后,在你的主线程中递归地进入树,并将工作发送给工人。如果任何工人“有时间”,它将从工作频道中挑选以下工作并进行处理。


var (

    wg   *sync.WaitGroup

    jobs chan string = make(chan string)

)


func loopFilesWorker() error {

    for path := range jobs {

        files, err := ioutil.ReadDir(path)

        if err != nil {

            wg.Done()

            return err

        }


        for _, file := range files {

            if !file.IsDir() {

                fmt.Println(file.Name())

            }

        }

        wg.Done()

    }

    return nil

}


func LoopDirsFiles(path string) error {

    files, err := ioutil.ReadDir(path)

    if err != nil {

        return err

    }

    //Add this path as a job to the workers

    //You must call it in a go routine, since if every worker is busy, then you have to wait for the channel to be free.

    go func() {

        wg.Add(1)

        jobs <- path

    }()

    for _, file := range files {

        if file.IsDir() {

            //Recursively go further in the tree

            LoopDirsFiles(filepath.Join(path, file.Name()))

        }

    }

    return nil

}


func main() {

    //Start as many workers you want, now 10 workers

    for w := 1; w <= 10; w++ {

        go loopFilesWorker()

    }

    //Start the recursion

    LoopDirsFiles(globals.SrcPath)

    wg.Wait()

}


查看完整回答
反对 回复 2022-11-28
  • 1 回答
  • 0 关注
  • 251 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信