在实际项目中我们可能有下面的需求:
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 键时:
上面的代码过于简单,一般我们会是用下面代码的方式来处理的。
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 的执行效果:
停止监听
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中处理信号非常简单,但是关于信号本身需要了解的还有很多,建议可以参考《Unix高级编程》中的信号篇章。
参考资料:
golang信号signal的处理
http://www.01happy.com/golang-signal/
Go中的系统Signal处理
http://tonybai.com/2012/09/21/signal-handling-in-go/