いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-611 (何もせずジーッと待機しているだけのプログラム)(chan, time.Sleep, signal.NotifyContext)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。大した内容じゃないのですが、たまに聞かれるのでここにメモしておきます。

たまにですが、何もせずにただただジーッとしてるだけのプログラムが欲しいときがあります。特定のプロセスの存在を判定して何かをするプログラムがあったりする場合とか。

そういうときに以下のように

package main

func main() {
        c := make(chan struct{})
        <-c
}

としてしまうかもしれませんが、これは動作しません。

$ go run .
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
        /home/dev/app/main.go:5 +0x25
exit status 2

まあ、そりゃそうですね。

なので、以下のようにする人が結構います。

package main

import "time"

func main() {
        for {
                time.Sleep(1 * time.Second)
        }
}

これでも目的は果たせるのですが、無限にsleepでループしているのがちょっと無駄ってなります。不要なシステムコール(約1秒毎)が定期的に発行され、ほんの僅かですがCPUも消費しちゃう。

こういうときは、素直にシグナルハンドラを張ってシグナル待ちをするのが一番素直かと個人的には思います。

package main

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

func main() {
        ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
        <-ctx.Done()
}

signal.NotifyContext は、キャンセルのための stop を返してくれるのですが、このプログラムはシグナルを受信すると即座に終了するため、技術的に不要です。

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。