Select 了解有无goroutine的频道选择
大家好,我的社区, 我正在使用Go将观察者设置为文件。我的函数看起来像Select 了解有无goroutine的频道选择,select,go,closures,channel,goroutine,Select,Go,Closures,Channel,Goroutine,大家好,我的社区, 我正在使用Go将观察者设置为文件。我的函数看起来像 func SetWatcher(filename string) { fmt.Println("Setting watcher to file ", filename) Watcher, err = fsnotify.NewWatcher() if err != nil { fmt.Println("inotify errored. Other methods needs to be
func SetWatcher(filename string) {
fmt.Println("Setting watcher to file ", filename)
Watcher, err = fsnotify.NewWatcher()
if err != nil {
fmt.Println("inotify errored. Other methods needs to be implemented.")
panic(err)
}
if err != nil {
log.Fatal(err)
}
done := make(chan bool)
go func() {
for {
select {
case event := <-Watcher.Events:
if event.Op == fsnotify.Remove {
fmt.Println("File removed, needs to kill the process.")
} else if event.Op == fsnotify.Rename {
fmt.Println("File renamed, need to restart seeking.")
}
case err := <-Watcher.Errors:
log.Println("error:", err)
}
}
}()
err = Watcher.Add(filename)
if err != nil {
log.Fatal(err)
}
<-done
}
w := &Watcher{
fd: fd,
poller: poller,
watches: make(map[string]*watch),
paths: make(map[int]string),
Events: make(chan Event, 10), // Made it buffered here
Errors: make(chan error),
done: make(chan struct{}),
doneResp: make(chan struct{}),
}
但是,如果我试图删除goroutine中运行的闭包并将其作为
func SetWatcher(filename string) {
fmt.Println("Setting watcher to file ", filename)
Watcher, err = fsnotify.NewWatcher()
if err != nil {
fmt.Println("inotify errored. Other methods needs to be implemented.")
panic(err)
}
if err != nil {
log.Fatal(err)
}
//defer Watcher.Close()
//done := make(chan bool)
//go func() {
// for {
select {
case event := <-Watcher.Events:
if event.Op == fsnotify.Remove {
fmt.Println("File removed, needs to kill the process.")
} else if event.Op == fsnotify.Rename {
fmt.Println("File renamed, need to restart seeking.")
}
case err := <-Watcher.Errors:
log.Println("error:", err)
}
//}
//}()
err = Watcher.Add(filename)
if err != nil {
log.Fatal(err)
}
//<-done
}
而不是从频道接收并继续等待
我已经了解到这可能是由于非缓冲通道造成的。为了验证这一点,我修改了库以使用缓冲通道,生成新观察者的函数部分如下所示
func SetWatcher(filename string) {
fmt.Println("Setting watcher to file ", filename)
Watcher, err = fsnotify.NewWatcher()
if err != nil {
fmt.Println("inotify errored. Other methods needs to be implemented.")
panic(err)
}
if err != nil {
log.Fatal(err)
}
done := make(chan bool)
go func() {
for {
select {
case event := <-Watcher.Events:
if event.Op == fsnotify.Remove {
fmt.Println("File removed, needs to kill the process.")
} else if event.Op == fsnotify.Rename {
fmt.Println("File renamed, need to restart seeking.")
}
case err := <-Watcher.Errors:
log.Println("error:", err)
}
}
}()
err = Watcher.Add(filename)
if err != nil {
log.Fatal(err)
}
<-done
}
w := &Watcher{
fd: fd,
poller: poller,
watches: make(map[string]*watch),
paths: make(map[int]string),
Events: make(chan Event, 10), // Made it buffered here
Errors: make(chan error),
done: make(chan struct{}),
doneResp: make(chan struct{}),
}
但行为是一样的。有人能帮我理解为什么在goroutine中,频道的阅读是有效的,而在没有goroutine的情况下是无效的
谢谢。我对fsnotify不太熟悉,但是在调用
Watcher.Add()
来查看文件之前,它似乎不会在频道上发送任何内容,但是在第二个版本中,Watcher.Add()
发生在选择
之后。在这种情况下,select将永远被阻止,因为没有任何东西会被通知为未调用Watcher.Add()
。因此出现了僵局