這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
捕捉和處理訊號可以實現優雅start和restart等。golang的signal提供了相關的方法。這裡是一個模板,目錄結構:
├── sig│ └── sig.go└── test.go
先看如何調用:
1.new出一個對象
2.register訊號與對應的處理函數
3.定義os.Signal類型的channel,調用signal.Notify
4.for+select迴圈,原有邏輯放在default分支中。
package main import ( . "./sig" "fmt" "os" "os/signal" "syscall" "time") var stopFlag_ bool func main() { sigHandler := SignalSetNew() sigHandler.Register(syscall.SIGQUIT, sigHandlerFunc) sigHandler.Register(syscall.SIGUSR1, sigHandlerFunc) sigHandler.Register(syscall.SIGUSR2, sigHandlerFunc) sigChan := make(chan os.Signal, 10) signal.Notify(sigChan) for true { select { case sig := <-sigChan: err := sigHandler.Handle(sig, nil) if err != nil { fmt.Printf("[ERROR] unknown signal received: %v\n", sig) os.Exit(1) } default: time.Sleep(time.Duration(3) * time.Second) } }} func sigHandlerFunc(s os.Signal, arg interface{}) { switch s { case syscall.SIGUSR1: // check fmt.Printf("stopping Status : %v\n", stopFlag_) case syscall.SIGUSR2: // run formerFlag := stopFlag_ stopFlag_ = false fmt.Printf("stopping Status changed from %v to %v\n", formerFlag, stopFlag_) case syscall.SIGQUIT: // stop formerFlag := stopFlag_ stopFlag_ = true fmt.Printf("stopping Status changed from %v to %v\n", formerFlag, stopFlag_) }}
sig包(sig/sig.go)的定義:
package sig import ( "fmt" "os") type SignalHandler func(s os.Signal, arg interface{}) type SignalSet struct { m map[os.Signal]SignalHandler} func SignalSetNew() *SignalSet { ss := new(SignalSet) ss.m = make(map[os.Signal]SignalHandler) return ss} func (set *SignalSet) Register(s os.Signal, handler SignalHandler) { if _, found := set.m[s]; !found { set.m[s] = handler }} func (set *SignalSet) Handle(sig os.Signal, arg interface{}) (err error) { if _, found := set.m[sig]; found { set.m[sig](sig, arg) return nil } else { return fmt.Errorf("No handler available for signal %v", sig) } panic("won't reach here")}