【问题标题】:What's the best practices to run a background task along with server listening运行后台任务和服务器监听的最佳实践是什么
【发布时间】:2017-02-15 13:57:21
【问题描述】:

我是 Go 新手。假设我有一个服务器正在监听 HTTP 请求,同时我需要检查 Redis 通知以便更新数据。下面是一个例子:

func checkExpire() {
    for {
        switch msg := pubSubConn.Receive().(type) {
        case redis.Message:
        ...
    }
}

server.ListenAndServe()

简单地将checkExpire 放入 goroutine 是一个好的解决方案吗?

go func() {
    for {
        switch msg := pubSubConn.Receive().(type) {
        case redis.Message:
        ...
    }
}()

【问题讨论】:

  • 为什么不呢?应该没问题。
  • 我不确定你在问什么,goroutines 是你在 Go 中同时运行某些东西的方式。你还会做什么?
  • 请注意,goroutines 不会阻止主进程退出。您可能需要在 main() 的末尾使用for {} 阻止。 edit 实际上 server.ListenAndServe 应该阻塞
  • @Plato 对不起,我应该把ListenAndServe 放在checkExpire 的下面。

标签: go goroutine


【解决方案1】:

是的,请记住 main 也是一个 goroutine,这是工作代码:

package main

import (
    "fmt"
    "net/http"
    "time"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func checkExpire() {
    for {
        // do some job
        fmt.Println(time.Now().UTC())
        time.Sleep(1000 * time.Millisecond)
    }
}

func main() {
    go checkExpire()
    http.HandleFunc("/", handler) // http://127.0.0.1:8080/Go
    http.ListenAndServe(":8080", nil)
}

运行代码并打开您的browser


永远不要使用空循环 (for{}) 请参阅:
Difference between the main goroutine and spawned goroutines of a Go program

空循环使用 100% 的 CPU 内核,根据您可能使用的用例等待某些操作:
- sync.WaitGroup 喜欢 this
- select {} 喜欢 this
- 频道
- time.Sleep

【讨论】:

  • 虽然在你回答之前我已经知道该怎么做了,但我还是会接受你的。谢谢。
  • 不要使用带有睡眠的 for {} 循环,最好使用 for _ := time.Tick(...) {} 循环并避免睡眠。
  • 在 GO 中使用 empty for 来阻塞 go-routine 是完全可以的。事实上,有时当你想做周期性任务时,这是你唯一的方法。例如,``` for { select{ case
  • @adonese 这不是空的,你的循环非常好,是答案所暗示的事情之一。这里的“空”字面意思是for {}
  • 我相信我回复的评论建议使用select 而不是for{} 进行阻止。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 2015-10-01
  • 2011-12-01
  • 2013-07-12
相关资源
最近更新 更多