捕捉和处理信号可以实现优雅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",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") }