What's the best practices to run a background task along with server listening

laike9m picture laike9m · Oct 6, 2016 · Viewed 10k times · Source

I'm new to Go. Say I have a server listening to HTTP request, and at the same time I need to check Redis notification so I can update data. Below is an example:

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

server.ListenAndServe()

Does simply putting checkExpire into a goroutine a good solution?

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

Answer

user6169399 picture user6169399 · Oct 7, 2016

Yes, and remember that main is a goroutine too, here is the working code:

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)
}

Run the code and open your browser.


And never use Empty loop (for{}) see:
Difference between the main goroutine and spawned goroutines of a Go program

Empty loop uses 100% of a CPU Core, to wait for some operation depending to the use case you may use:
- sync.WaitGroup like this
- select {} like this
- channels
- time.Sleep