我正在构建一个应用程序,以在每次代码更改时运行命令。我为此功能使用了fsnotify
。但是,我不明白它是如何等待主goroutine的。
我发现使用sync.WaitGroup
更惯用,但是我很好奇chan bool如何使goroutine在fsnotify
示例代码中等待。
我试图在done
的示例代码中删除fsnotify
,但它不是在等待goroutine,而是退出了。
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("event:", event)
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("modified file:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("error:", err)
}
}
}()
err = watcher.Add("/tmp/foo")
if err != nil {
log.Fatal(err)
}
<-done
答案 0 :(得分:1)
我不确定您要问什么,但是您提供的代码中有一个细微的错误。
done
通道是一种阻止动作完成的常见方法。它的用法如下:
done := make(chan X) // Where X is any type
go func() {
// Some logic, possibly in a loop
close(done)
}()
// Other logic
<-done // Wait for `done` to be closed
通道的类型无关紧要,因为(不需要)通过通道发送任何数据,因此bool
可以工作,但是struct{}
更为惯用,因为它表明无法发送任何数据
您的示例几乎执行此操作,只是它从未调用close(done)
。这是一个错误。这意味着代码将始终在<-done
处永远等待,从而否定了已完成通道的全部目的。您的示例代码将永不退出。
这意味着您所提供的代码也可以写为:
go func() {
// Do stuff
}()
// Do other stuff
<Any code that blocks forever>
因为有无数种方法可以永远阻止阻塞-在实践中没有一种有用-不需要示例中的通道。
答案 1 :(得分:-1)
根据我的研究,我在reddit.com上找到了一个人的答案。不过,这是种技巧,使用<-done
可使主goroutine等待chan完成任何值,最终此应用将继续运行,供fsnotify
观看并将事件发送到主goroutine。