golang信號signal的處理


在實際項目中我們修改了配置文件后,希望在不重啟進程的情況下重新加載配置文件,這時候就需要通過信號傳遞來進行處理了。golang中對信號的處理主要使用os/signal包中的兩個方法:一個是notify方法用來監聽收到的信號;一個是 stop方法用來取消監聽。下面給一個些示例。

監聽信號

notify方法原型

func Notify(c chan<- os.Signal, sig ...os.Signal)

第一個參數表示接收信號的管道
第二個及后面的參數表示設置要監聽的信號,如果不設置表示監聽所有的信號。

package main

import (
	"fmt"
	"os"
	"os/signal"
	//"syscall"
)

func main() {
	c := make(chan os.Signal)
	signal.Notify(c)
	//監聽指定信號
	//signal.Notify(c, syscall.SIGHUP, syscall.SIGUSR2)

	//阻塞直至有信號傳入
	s := <-c
	fmt.Println("get signal:", s)
}

運行該程序后,搜索到該程序的進程編號,運行kill命令就可以看到信號的輸出。

終端1:

$ go run main.go
//此時處於阻塞狀態,當終端2執行kill時輸出如下信息
get signal: user defined signal 2

終端2:

$ ps -ef | grep main
501 839 543 0 11:16PM ttys000 0:00.03 go run main.go
501 842 839 0 11:16PM ttys000 0:00.00 /var/folders/s8/kbqz28xd3wl8q5rw8vsr129c0000gn/T/go-build384577908/command-line-arguments/_obj/exe/main
501 844 709 0 11:16PM ttys001 0:00.00 grep main
$ kill -USR2 842

當然這樣的程序在實際中並沒有什么用處,改進一下就可以用來接收信號並且處理一些內容了。

package main

import (
	"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 main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	c := make(chan os.Signal)
	signal.Notify(c, syscall.SIGUSR2)

	//當調用了該方法后,下面的for循環內<-c接收到一個信號就退出了。
	signal.Stop(c)

	for {
		s := <-c
		fmt.Println("get signal:", s)
	}

}

小結

golang中處理信號非常簡單,但是關於信號本身需要了解的還有很多,建議可以參考《Unix高級編程》中的信號篇章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM