這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
在實際項目中我們修改了設定檔後,希望在不重啟進程的情況下重新載入設定檔,這時候就需要通過訊號傳遞來進行處理了。golang中對訊號的處理主要使用os/signal包中的兩個方法:一個是notify方法用來監聽收到的訊號;一個是 stop方法用來取消監聽。下面給一個些樣本。
監聽訊號
notify方法原型
func Notify(c chan<- os.Signal, sig ...os.Signal)
第一個參數表示接收訊號的管道
第二個及後面的參數表示設定要監聽的訊號,如果不設定表示監聽所有的訊號。
package mainimport ("fmt""os""os/signal"//"syscall")func main() {c := make(chan os.Signal)signal.Notify(c)//監聽指定訊號//signal.Notify(c, syscall.SIGHUP, syscall.SIGUSR2)//阻塞直至有訊號傳入s := <-cfmt.Println("get signal:", s)}
運行該程式後,搜尋到該程式的進程編號,運行kill命令就可以看到訊號的輸出。
終端1:
$ go run main.go//此時處於阻塞狀態,當終端2執行kill時輸出如下資訊get signal: user defined signal 2
終端2:
$ ps -ef | grep main501 839 543 0 11:16PM ttys000 0:00.03 go run main.go501 842 839 0 11:16PM ttys000 0:00.00 /var/folders/s8/kbqz28xd3wl8q5rw8vsr129c0000gn/T/go-build384577908/command-line-arguments/_obj/exe/main501 844 709 0 11:16PM ttys001 0:00.00 grep main$ kill -USR2 842
當然這樣的程式在實際中並沒有什麼用處,改進一下就可以用來接收訊號並且處理一些內容了。
package mainimport ("fmt""os""os/signal""syscall""time")func main() {go signalListen()for {time.Sleep(10 * time.Second)}}func signalListen() {c := make(chan os.Signal)signal.Notify(c, syscall.SIGUSR2)for {s := <-c//收到訊號後的處理,這裡只是輸出訊號內容,可以做一些更有意思的事fmt.Println("get signal:", s)}}
主要就是開啟一個gorutine單獨處理訊號的監聽。
停止監聽
package mainimport ("fmt""os""os/signal""syscall")func main() {c := make(chan os.Signal)signal.Notify(c, syscall.SIGUSR2)//當調用了該方法後,下面的for迴圈內<-c接收到一個訊號就退出了。signal.Stop(c)for {s := <-cfmt.Println("get signal:", s)}}
小結
golang中處理訊號非常簡單,但是關於訊號本身需要瞭解的還有很多,建議可以參考《Unix進階編程》中的訊號篇章。
轉載請註明:快樂編程 » golang訊號signal的處理