我在go中遇到了filepath.Walk()的奇怪问题。它开始运行然后到达它刚刚挂起的点。我的CPU处于100%,没有错误,也没有继续。我查看了我正在浏览的目录,它挂起的位置没什么特别的,没有symlins或类似的东西。只是简单的目录和文件。这是我使用的代码:
type WatchDirs struct {
Dirs []string
}
//Watches ...Recursively walk the filesystem, entrypoint to file watching
func Watches(tops []string) error {
var dirs WatchDirs
for _, top := range tops {
err := filepath.Walk(top, func(path string, f os.FileInfo, err error) error {
if err != nil {
log.Println(err)
return err
}
log.Println("File: ", path)
if f.IsDir() {
//log.Println("Path: ", path)
dirs.Dirs = append(dirs.Dirs, path)
}
return nil
})
if err != nil {
log.Println(err)
}
log.Println("Continuing Loop")
}
log.Println("Starting Dedup: ")
dirs.Dedup()
log.Println("Post Dedup: ")
for _, dir := range dirs.Dirs {
log.Println(dir)
}
dirs.Watch()
return nil
}
//Dedup ...Remove all duplicate entires from configured directories
func (dirs *WatchDirs) Dedup() {
log.Println("deduping")
uniqueSet := make(map[string]bool, len(dirs.Dirs))
for _, x := range dirs.Dirs {
uniqueSet[x] = true
}
result := make([]string, 0, len(uniqueSet))
for x := range uniqueSet {
result = append(result, x)
}
dirs.Dirs = result
}
//Watch ...Watch the list of created directories for changes
func (dirs *WatchDirs) Watch() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event := <-watcher.Events:
log.Println("event:", event)
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("modified file:", event.Name)
}
case err := <-watcher.Errors:
log.Println("error:", err)
}
}
}()
for _, dir := range dirs.Dirs {
log.Println("Watching dir: ", dir)
err = watcher.Add(dir)
if err != nil {
log.Println(err)
}
}
<-done
}
编辑:为了清晰起见,添加了其他功能。
答案 0 :(得分:1)
我不是百分之百确定你的意图..然而,对我来说,宏计划似乎是想要将目录的路径附加到切片。您想检查是否添加了新内容,然后将该新目录添加到切片中。这是我的简单版本。每秒defined by the ticker
我同步路径的位置。我使用信号来说,“嘿,我想停止观察更改并打印出所有路径”。我还使用一个通道来收听来自stdin的命令来做其他事情(你可以肯定地建立一些东西)。
我无法确切地告诉您原始代码中的失败点。如果您的watching
有更改,那么除非您另有说明,否则代码应该是阻止的。
package main
import (
"bufio"
"io"
"log"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
)
type Watcher struct {
Dirs []DirInfo
Ticker *time.Ticker
Stop chan os.Signal
Command chan string
}
type DirInfo struct {
LastMod time.Time
Path string
}
func New() *Watcher {
return &Watcher{
Stop: make(chan os.Signal, 1),
Ticker: time.NewTicker(1 * time.Second),
Command: make(chan string),
}
}
func (w *Watcher) addPath(path string, f os.FileInfo) {
shouldAppend := true
for i, d := range w.Dirs {
if d.Path == path {
w.Dirs[i].LastMod = f.ModTime()
shouldAppend = false
break
}
}
if shouldAppend {
w.Dirs = append(w.Dirs, DirInfo{f.ModTime(), path})
}
}
func (w *Watcher) List() {
if len(w.Dirs) == 0 {
log.Println("Nothing to show")
return
}
for _, d := range w.Dirs {
log.Println(d.Path)
}
return
}
func (w *Watcher) isNew(path string, f os.FileInfo) bool {
for _, d := range w.Dirs {
if path == d.Path {
t := f.ModTime()
return t.After(d.LastMod)
}
}
return true
}
func (w *Watcher) Sync(tops []string) {
for _, top := range tops {
err := filepath.Walk(top, func(path string, f os.FileInfo, err error) error {
if err != nil {
return err
}
if f.IsDir() && w.isNew(path, f) {
w.addPath(path, f)
}
return nil
})
if err != nil {
log.Printf("Error %v\n", err)
}
}
}
func main() {
w := New()
tops := []string{}
signal.Notify(w.Stop, syscall.SIGINT, syscall.SIGTERM)
go func() {
s := bufio.NewScanner(os.Stdin)
for {
for s.Scan() {
w.Command <- s.Text()
}
}
}()
for {
select {
case <-w.Ticker.C:
w.Sync(tops)
case <-w.Stop:
log.Println("signalled to stop")
w.List()
os.Exit(0)
case cmd := <-w.Command:
switch cmd {
case "list":
w.List()
}
}
}
}