2016-09-19 55 views
2

我需要在Golang中使用文件系统,并且需要在重新启动后才能恢复扫描。如何在Golang中使用seekdir/telldir?

在C中,我可以通过telldir()然后在seekdir()恢复时执行此操作。

Golang只提供了一个filepath.Walk()函数,但它没有提供从特定路径或点开始移动文件系统的方法。

这使得效率低下的大型文件系统

周围没有任何办法吗?

回答

2

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来解决此限制。

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 
    }) 
}