go:优雅的退出http服务 在退出http服务的时候,可能要等待后台的某一个协程完成。此时,需要这样: ## 处理sigterm信号 go的信号处理很巧妙,用的是chan转发。 这是一个官方示例: ```go package main import "fmt" import "os" import "os/signal" import "syscall" func main() { // Go signal notification works by sending `os.Signal` // values on a channel. We'll create a channel to // receive these notifications (we'll also make one to // notify us when the program can exit). sigs := make(chan os.Signal, 1) done := make(chan bool, 1) // `signal.Notify` registers the given channel to // receive notifications of the specified signals. signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) // This goroutine executes a blocking receive for // signals. When it gets one it'll print it out // and then notify the program that it can finish. go func() { sig := <-sigs fmt.Println() fmt.Println(sig) done <- true }() // The program will wait here until it gets the // expected signal (as indicated by the goroutine // above sending a value on `done`) and then exit. fmt.Println("awaiting signal") <-done fmt.Println("exiting") } ``` ## 把server.ListenAndServe() 跑在协程里 此外,server.ListenAndServe()不能跑在main中,因为在main中,要处理其它任务。如何使main阻塞呢?上段代码done这个协程是能派上用场的。 示例代码如下: > https://stackoverflow.com/questions/39320025/how-to-stop-http-listenandserve ```go package main import ( "log" "io" "time" "net/http" ) func startHttpServer() *http.Server { srv := &http.Server{Addr: ":8080"} http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "hello world\n") }) go func() { if err := srv.ListenAndServe(); err != nil { // cannot panic, because this probably is an intentional close log.Printf("Httpserver: ListenAndServe() error: %s", err) } }() // returning reference so caller can call Shutdown() return srv } func main() { log.Printf("main: starting HTTP server") srv := startHttpServer() log.Printf("main: serving for 10 seconds") time.Sleep(10 * time.Second) log.Printf("main: stopping HTTP server") // now close the server gracefully ("shutdown") // timeout could be given instead of nil as a https://golang.org/pkg/context/ if err := srv.Shutdown(nil); err != nil { panic(err) // failure/timeout shutting down the server gracefully } log.Printf("main: done. exiting") } ``` 将这两段代码整合下,相信就很简单了。 来自 大脸猫 写于 2018-05-03 23:07 -- 更新于2020-10-19 13:06 -- 0 条评论