signal.Notify
を使うとチャネルでシグナルを受け取ることができる。
package main import ( "fmt" "os" "os/signal" "syscall" ) func main() { sigCh := make(chan os.Signal) signal.Notify(sigCh, syscall.SIGINT) s := <-sigCh fmt.Printf("%T %v\n", s, s) }
Ctrl+cを実行するとSIGINTがプログラムに通知されてs
の中に受信したシグナルが代入される。
signal.Notify
を使ってシグナルをプログラムで受信することで、(シグナルを受信した後に何かしらの停止処理を実行することで)プログラムを安全に止めることができる。
シグナル受信用のチャネルの型はos.Signal
を使う。os.Signal
はインターフェースとして定義されている。
type Signal interface { String() string Signal() // to distinguish from other Stringers }
os - The Go Programming Language
通知されるシグナルは全てこのインターフェースを実装している。
通知されるシグナルはsyscall
に定義されていて、signal.Notify
で受信したいシグナルを指定するときはここにある定義を使う。
syscall - The Go Programming Language
const ( SIGABRT = Signal(0x6) SIGALRM = Signal(0xe) SIGBUS = Signal(0x7) SIGCHLD = Signal(0x11) SIGCLD = Signal(0x11) SIGCONT = Signal(0x12) SIGFPE = Signal(0x8) SIGHUP = Signal(0x1) SIGILL = Signal(0x4) SIGINT = Signal(0x2) ・ ・ ・
↑
定義を見るとSignal
型でキャストされて整数を設定している。ここのSignal
はos.Signal
ではなく、syscall.Signal
である。
syscall
で定義されているSignal
は以下のようになっている。
type Signal int
これに加えて、os.Signal
インターフェースを実装している。なので先にあったように受信する型をos.Signal
に指定すればsyscall.Signal
をそのまま受け取ることができる。