我开始通过创建一个简单的http服务器来学习golang
func main() {
f, err := os.OpenFile("testlogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
fmt.Println("error opening file: %v", err)
}
defer f.Close()
log.SetOutput(f)
http.HandleFunc("/", defaultHandler)
http.HandleFunc("/check", checkHandler)
serverErr := http.ListenAndServe("127.0.0.1:8080", nil) // set listen port
if serverErr != nil {
log.Println("Error starting server")
} else {
fmt.Println("Started server on - 127.0.0.1:8080" )
}
}
上面的代码将在8080启动本地服务器,我可以通过浏览器点击路由。这一切都很好!
但是,现在我想运行一个单独的go例程来监视文件 -
func initWatch() string{
watcher, err := fsnotify.NewWatcher()
if err != nil {
fmt.Println(err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event := <-watcher.Events:
if ( event.Op&fsnotify.Remove == fsnotify.Remove || event.Op&fsnotify.Rename == fsnotify.Rename ) {
fmt.Println("file removed - ", event.Name)
}
case err := <-watcher.Errors:
fmt.Println("error:", err)
}
}
}()
err = watcher.Add("sampledata.txt")
if err != nil {
fmt.Println(err)
}
<-done
}
现在,如果我调用函数initWatch()
BEFORE http.ListenAndServe("127.0.0.1:8080", nil)
,那么我无法通过浏览器访问服务器路由(ex-localhost:8080),因为服务器没有产生。
前 -
initWatch()
serverErr := http.ListenAndServe("127.0.0.1:8080", nil) // set listen port
如果我调用函数initWatch()
AFTER http.ListenAndServe("127.0.0.1:8080", nil)
,则文件观察程序功能无效。
前 -
serverErr := http.ListenAndServe("127.0.0.1:8080", nil) // set listen port
initWatch()
如何让initWatch()
(文件观察者)和http服务器同时运行?
感谢您的帮助。
答案 0 :(得分:3)
两个来电,initWatch()
和http.ListenAndServe("127.0.0.1:8080", nil)
都会让主要的goroutine永远等待。 initWatch()
正在等待<-done
语句中的值,并且永远不会得到一个值。您应该在另一个goroutine中运行initWatch
或http.ListenAndServe
,例如go initWatch()
。或者也许从另一个goroutine向done
频道发送一个值。
答案 1 :(得分:2)
你可以在单独的goroutine中启动观察者。服务器结束后 - 您发送信号退出观察者。像:
done := initWatch()
serverErr := http.ListenAndServe("127.0.0.1:8080", nil)
done <- true
接下来稍微修改观察者 - 返回通道,通知停止工作。还在工作goroutine监听退出信号。
func initWatch() chan bool {
watcher, err := fsnotify.NewWatcher()
if err != nil {
fmt.Println(err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event := <-watcher.Events:
if ( event.Op&fsnotify.Remove == fsnotify.Remove || event.Op&fsnotify.Rename == fsnotify.Rename ) {
fmt.Println("file removed - ", event.Name)
}
case err := <-watcher.Errors:
fmt.Println("error:", err)
// listen exit signal
case <- done:
break
}
}
}()
err = watcher.Add("sampledata.txt")
if err != nil {
fmt.Println(err)
}
return done
}