🐕
errgroupの整理
なぜ必要か
goroutineを作成したとき、デフォルトでは作成元はgoroutineの終了を待たない。
例えば、以下のようにmain関数を定義しても、一回もhelloが出力されないことがあり得る。
このとき、ナイーブな解決策として、channelを渡して終了を待ち合わせる。
これですべての関数呼出しを待てるようになった。しかし、関数呼出しを待つchannelをいちいち作成したりするのはかなり負担が大きい。
そこで、sync.WaitGroup
を用いることで、終了を待ち合わせることができる。
ただし、どこかのgoroutineでエラーが発生したとき、その状態を把握するためにはひと工夫が必要。
ここで、errorgroupを用いることで、sync.WaitGroupで発生した最初のエラーを知ることができる。
1つでもエラーが発生したら全てのgoroutineを閉じてアプリケーションを終了するみたいな処理を実装する場合に、アプリケーションが終了した原因を知るのに便利。
使い方
func (*Group) Goでgoroutineを作成できる。
例えば、以下のようにfunc (*Group) Waitで複数goroutineを待ち合わせて、エラーがあったらそれを返す。
group, gCtx := errgroup.WithContext(ctx)
group.Go(func() error {
// gRPCサーバーの立ち上げ
...
}
group.Go(func() error(
// gRPCサーバーの終了処理
<-gCtx.Done()
stopped := make(chan struct{})
go func() {
a.RPC().GracefulStop()
close(stopped)
}()
...
return group.Wait()
Discussion