在实际项目中我们可能有下面的需求:
1、修改了配置文件后,希望在不重启进程的情况下重新加载配置文件;
2、当用 Ctrl + C 强制关闭应用后,做一些必要的处理;

这时候就需要通过信号传递来进行处理了。golang中对信号的处理主要使用os/signal包中的两个方法:一个是notify方法用来监听收到的信号;一个是 stop方法用来取消监听。

 

监听信号

notify方法原型
func Notify(c chan<- os.Signal, sig ...os.Signal)
第一个参数表示接收信号的管道
第二个及后面的参数表示设置要监听的信号,如果不设置表示监听所有的信号。

 

下面是一个非常简单地例子:

package main 
import (    
    "fmt"     
    "os"     
    "os/signal"     
) func main() {    
    c := make(chan os.Signal)     
    signal.Notify(c)     //signal.Notify(c, syscall.SIGHUP, syscall.SIGUSR2)  //监听指定信号 
    s := <-c //阻塞直至有信号传入    
    fmt.Println("get signal:", s)     
}

执行效果:

当按下 ctrl +c 键时:

Golang的 signal_Go

上面的代码过于简单,一般我们会是用下面代码的方式来处理的。

package main 
import (    
    "fmt"     
    "os"     
    "os/signal"     
    "time"     
) func main() {    
    go signalListen()     
    time.Sleep(time.Hour)     
} func signalListen() {    
    c := make(chan os.Signal)     
    signal.Notify(c)     
    for {     
        s := <-c     
        //收到信号后的处理,这里只是输出信号内容,可以做一些更有意思的事     
        fmt.Println("get signal:", s)     
        os.Exit(1)     
    }     
}

执行效果:

这是在进入应用后, 按了四次回车,然后再按 Ctrl +C 的执行效果:

Golang的 signal_配置文件_02

 

停止监听

package main 
import (    
    "fmt"     
    "os"     
    "os/signal"     
) func main() {    
    c := make(chan os.Signal)     
    signal.Notify(c)     //当调用了该方法后,下面的for循环内<-c接收到一个信号就退出了。    
    signal.Stop(c)     for {    
        s := <-c     
        fmt.Println("get signal:", s)     
    }     
}

执行效果:

Golang的 signal_Go_03

 

golang中处理信号非常简单,但是关于信号本身需要了解的还有很多,建议可以参考《Unix高级编程》中的信号篇章。

 

 

参考资料:

golang信号signal的处理
http://www.01happy.com/golang-signal/

Go中的系统Signal处理
http://tonybai.com/2012/09/21/signal-handling-in-go/