我需要在Golang中使用文件系统,并且需要在重新启动后才能恢复扫描。如何在Golang中使用seekdir/telldir?
在C中,我可以通过telldir()
然后在seekdir()
恢复时执行此操作。
Golang只提供了一个filepath.Walk()
函数,但它没有提供从特定路径或点开始移动文件系统的方法。
这使得效率低下的大型文件系统
周围没有任何办法吗?
我需要在Golang中使用文件系统,并且需要在重新启动后才能恢复扫描。如何在Golang中使用seekdir/telldir?
在C中,我可以通过telldir()
然后在seekdir()
恢复时执行此操作。
Golang只提供了一个filepath.Walk()
函数,但它没有提供从特定路径或点开始移动文件系统的方法。
这使得效率低下的大型文件系统
周围没有任何办法吗?
为filepath.walk
的签名是:
func Walk(root string, walkFn WalkFunc) error
的文档指出它开始于被root
和回调函数的签名(walkFn
)指定的目录是:
type WalkFunc func(path string, info os.FileInfo, err error) error
所以你可以在任何给定的目录下开始扫描,并以root作为文件系统。你不能在目录中部分开始,但你可以选择性地修剪你正在走的树。
还有一个“魔术”返回值filepath.SkipDir
,它跳过一个目录(如果在目录上调用回调时返回)或其余文件在目录中(如果在调用回调时返回文件)。
这可能足以让你想要的行为,但有点难以告诉你的问题。您不能跳出filepath.Walk
调用,然后再继续。但是,如果您主要关注回调花费时间完成,则可以通过在walkFn
回调中产生goroutine来解决此限制。
您可以编写自己的状态机:
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
})
}