golang优雅退出的方法
Channel关闭原则:不要在消费端关闭channel,不要在有多个并行的生产者时对channel执行关闭操作。
// 一个循环里只从一个工作channel里读数据
go func(in <-chan int) {
for x := range in { // 当channel "in"被关闭时会结束循环
fmt.Printf("Process %d\n", x)
}
}(inCh)
// 一个循环里需要从一个工作channel里读数据,同时还需响应控制channel
go func() {
for {
select {
case x, ok := <-in: // channel里读数据,处理数据。当channel关闭时ok为false
if !ok {
return
}
fmt.Printf("Process %dn", x)
processdCnt++
case <-t.C: // 这个channel可以用来打印当前处理了多少次了
fmt.Printf("working, processdCnt = %d\n", processedCnt)
}
}
}()
// 一个循环中要处理多个工作channel并且只有某些工作channel都被关闭了才退出
go func() {
for {
select {
case x, ok := <-in1:
if !ok {
in1 = nil // 设置为nil后,后面select不会再进入
}
// process ...
case y, ok := <-in2:
if !ok {
in2 = nil
}
// process ...
case <-t.C:
fmt.Printf("working, processdCnt = %d\n", processedCnt)
}
if in1 == nil && in2 == nil {
return // 所关心的通道都为nil,所以退出
}
}
}()
// 使用专门的退出channel主动退出,此时的工作channel可能还为关闭
func worker(stopCh <-chan struct{}) {
go func() {
def fmt.Println("worker exit")
for {
select {
case <-stopCh:
fmt.Println("Recv stop signal")
return
case <-t.C:
fmt.Println("Working ...")
}
}
}()
return
}
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gorilla/mux" // need to use dep for package management
)
func TestEndpoint(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("Test is what we usually do"))
}
func main() {
router := mux.NewRouter()
router.HandleFunc("/test", TestEndpoint).Methods("GET")
srv := &http.Server{
Addr: ":8080",
Handler: router,
}
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
log.Print("Server Started")
<-done
log.Print("Server Stopped")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer func() {
// extra handling here
cancel()
}()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("Server Shutdown Failed:%+v", err)
}
log.Print("Server Exited Properly")
}
// https://medium.com/honestbee-tw-engineer/gracefully-shutdown-in-go-http-server-5f5e6b83da5a