Как чан бул заставляет ждать горутин? - PullRequest
0 голосов
/ 09 мая 2019

Я создаю приложение для запуска команды каждый раз, когда изменяется код.Я использую fsnotify для этой функции.Но я не могу понять, как он ожидает основной программы.

Я обнаружил, что использование sync.WaitGroup более идиоматично, но мне любопытно, как из-за того, что chan bool делает goroutine, ждет в fsnotifyпример кода.

Я попытался удалить done в примере кода fsnotify, но он не ожидает выполнения процедуры, просто завершен.

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 ]

1 голос
/ 10 мая 2019

Я не совсем уверен, о чем вы спрашиваете, но в коде, который вы предоставили, есть небольшая ошибка.

Канал 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>

Поскольку существует бесчисленное множество способовблокируйте навсегда - ни один из них никогда не будет полезен на практике - канал в вашем примере не нужен.

0 голосов
/ 10 мая 2019

Согласно моему исследованию, я нашел ответ от одного парня в reddit.com. Это своего рода хитрость, хотя использование <-done заставляет основную программу ожидать любого значения от chan, в конце концов это приложение продолжает работать для fsnotify, чтобы посмотреть и отправить событие в главную программу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...