web-dev-qa-db-ja.com

プロジェクトのメインのゴルーチンは永遠に眠りますか?

main goroutineを永久にスリープさせるAPIはありますか?

つまり、プロジェクトを停止するときを除いて、常にプロジェクトを実行したいのです。

19
Dev Zhou

"睡眠"

CPUを「使い果たす」ことなく、永久にブロックする多数の構成を使用できます。

たとえば、selectなし(およびcaseなし)のdefault

_select{}
_

または、誰も何も送信しないチャネルから受信します。

_<-make(chan int)
_

または、nilチャネルからの受信も永久にブロックされます。

_<-(chan int)(nil)
_

または、nilチャネルでの送信も永久にブロックされます。

_(chan int)(nil) <- 0
_

または、すでにロックされている_sync.Mutex_をロックします。

_mu := sync.Mutex{}
mu.Lock()
mu.Lock()
_

やめる

終了する方法を提供したい場合は、単純なチャネルでそれを行うことができます。 quitチャネルを提供し、そこから受信します。終了する場合は、quitチャネルを閉じます。「閉じたチャネルでの受信操作はいつでもすぐに続行でき、以前に送信された値を受信した後、要素タイプの ゼロ値 を生成します。 "。

_var quit = make(chan struct{})

func main() {
    // Startup code...

    // Then blocking (waiting for quit signal):
    <-quit
}

// And in another goroutine if you want to quit:
close(quit)
_

close(quit)を発行すると、いつでもアプリが終了する可能性があることに注意してください。 仕様:プログラム実行: からの引用

プログラムの実行は、メインパッケージを初期化してから、関数mainを呼び出すことから始まります。その関数呼び出しが戻ると、プログラムは終了します。 他の(-main以外の)ゴルーチンが完了するのを待ちません。

close(quit)が実行されると、main()関数の最後のステートメントを続行できます。つまり、main goroutineが戻ることができるため、プログラムは終了します。

33
icza

使用するケースによって、必要な睡眠の種類を選択できます。

@iczaは、文字通り永遠に眠るための優れたシンプルなソリューションを提供しますが、システムを正常にシャットダウンできるようにしたい場合は、もう少しお菓子を提供したいと思います。

あなたはこのようなことをすることができます:

func mainloop() {
    exitSignal := make(chan os.Signal)
    signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM)
    <-exitSignal

    systemTeardown()
}

そしてあなたのメインで:

func main() {
    systemStart()
    mainloop()
}

このようにして、メインに永久にスリープするように要求できるだけでなく、コードがOSからINTまたはTERM信号を受信した後、ctrl+Cのように適切なシャットダウンを実行できます。またはkill

7
nevets