chan bool如何让goroutine等待?

时间:2019-05-09 14:43:19

标签: go

我正在构建一个应用程序,以在每次代码更改时运行命令。我为此功能使用了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

2 个答案:

答案 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。