捕捉和处理信号可以实现优雅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") }
有疑问加站长微信联系(非本文作者)