我需要在Golang中使用文件系统,并且需要能够在重新启动后恢复扫描。
在C中,我可以通过telldir()
执行此操作,然后在恢复时执行seekdir()
。
Golang只提供filepath.Walk()
函数,但无法从特定路径或点开始遍历文件系统。
这使得大型文件系统效率低下
周围有什么办法吗?
答案 0 :(得分:2)
filepath.walk
的签名是:
func Walk(root string, walkFn WalkFunc) error
文档说明它从root
指定的目录开始,并且回调函数(walkFn
)的签名是:
type WalkFunc func(path string, info os.FileInfo, err error) error
因此,您可以在任何给定目录中开始扫描,并以文件系统作为根目录运行文件系统。您无法从目录开始,但您可以选择性地修剪您正在行走的树。
还有一个"魔法"返回值filepath.SkipDir
,它跳过目录(如果在目录上调用回调时返回)或目录中的其余文件(如果在文件上调用回调时返回)。
这可能足以获得您想要的行为,但从您的问题中说出来有点难以理解。你不能打破filepath.Walk
调用,然后再恢复它。但是,如果你主要关注回调需要时间来完成,你可以通过在walkFn
回调中产生goroutine来解决这个限制。
答案 1 :(得分:0)
您可以编写自己的状态机:
1-使用filepath.Walk()
一直走完并缓冲结果,然后使用状态(快速)的缓冲区。
2-将root string
保存为暂停状态,然后从头开始扫描,直到到达保存的路径(慢)。
3-您可以使用频道,例如此工作样本:
(试试The Go Playground):
package main
import (
"fmt"
"os"
"path/filepath"
"sync"
"time"
)
var dirs = make(chan string, 10)
var wg sync.WaitGroup
func main() {
wg.Add(1)
go GetDirectories(`../`, `*`)
fmt.Println()
fmt.Println(<-dirs)
fmt.Println(<-dirs)
fmt.Println()
time.Sleep(1 * time.Second) // pause
for dir := range dirs {
fmt.Println(dir)
}
wg.Wait()
fmt.Println(`Done.`)
}
// Returns the names of the subdirectories (including their paths)
// that match the specified search pattern in the specified directory.
func GetDirectories(root, pattern string) {
defer wg.Done()
defer close(dirs)
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if !fi.IsDir() {
return nil
}
matched, err := filepath.Match(pattern, fi.Name())
if err != nil {
return err
}
if !matched {
return nil
}
dirs <- path //dirs = append(dirs, path)
return nil
})
}