⛸
Go main終了によるgoroutine終了の抑止
前提
メインゴルーチンが終了するとプログラムは終了するので、goroutineを切った場合の処理も中断される
それを止めない方法の紹介
あるコンテナを常駐させるときなどに便利
主にchannel待ちを使う
以下のプログラムは(goroutineの実行状態を無視して)即終了する
func main() {
go func() {
for {
// 処理
}
}()
}
select {}
アドホックな方法1
package main
func main() {
go func() {
for {
// 処理
}
}()
select {}
}
select
はチャネルの受信を待って区別して分岐、だが終了条件を定義していなければずっと待ちに入り、mainは終了しない
受信待ち
アドホックな方法2
package main
func main(){
go func() {
for {
// 処理
}
}()
ch := make(chan struct{})
<-ch
}
chの受信を待つがchに対し送信をしていないため、ずっと受信を待ち続けmainは終了しない
sync.WaitGroup.Done()しない
使い道違うだろうけど、一応
package main
import "sync"
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
for {
// 処理
}
}()
wg.Wait()
}
Done()しないとWait()したままなので、mainは終了しない
この例はむしろDone()漏れしたので終了すべきプログラムが終了しない、というコーディング上のポカとしてありそう
ちなみに
いずれの例も、goroutineを切らずに停止しない処理だけ書いて実行すると、デッドロックになる
package main
func main() {
select {}
}
$ go run .
fatal error: all goroutines are asleep - deadlock!
Discussion