サンプル付き Go: シグナル

時々、Go プログラムにUnix シグナルをインテリジェントに処理してほしくなります。例えば、サーバーがSIGTERMを受け取るときには正常にシャットダウンし、コマンドラインツールは SIGINTを受け取ると入力処理を停止するようにしたい場合があります。次のようにチャネルを使用して Go でシグナルを処理します。

package main
import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)
func main() {

Go のシグナル通知は、チャネルにos.Signalの値を送信することで機能します。このような通知を受けるためのチャネルを作成します。このチャネルはバッファリングされる必要があることに注意してください。

    sigs := make(chan os.Signal, 1)

signal.Notifyは、指定されたシグナルの通知を受け取るために与えられたチャネルを登録します。

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

ここではメイン関数でsigsから受け取ることができますが、現実的な正常終了のシナリオを示すために、別のゴルーチンでこれを行う方法についても見てみましょう。

    done := make(chan bool, 1)

このゴルーチンは、シグナルに対するブロッキング受信を実行します。受信すると、それを表示し、プログラムに終了できるように通知します。

    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
    }()

プログラムは、上記で説明されているゴルーチンがdoneに対して値を送信することで指定された予期されたシグナルを受信するまでここで待機してから終了します。

    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}

このプログラムを実行すると、シグナルが待機するブロックされます。ctrl-C(ターミナルでは ^Cと表示)を入力することで、SIGINTシグナルを送信し、プログラムにinterruptを表示させて終了させることができます。

$ go run signals.go
awaiting signal
^C
interrupt
exiting

次の例: 終了