這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
在實際項目中我們可能有下面的需求:
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/