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