errgroup.WithContext()
の返り値であるcontextは、非同期処理に対するcontextであり、それ以外の場所で使用してはいけない。
返り値のcontextを、それ以降の関数で使用すると、canceled contextなので不具合が発生する可能性がある。
Wait()
した箇所で、contextがcanceledになる。それ以降の処理で使用しない方がいい。以下の様にするのがよさそう。
// OK
eg, egCtx := errgroup.WithContext(ctx)
// NG
eg, ctx := errgroup.WithContext(ctx)
eg, ctx := errgroup.WithContext(ctx)
だと、以下の様になってしまう。
func main() {
ctx := context.Background()
fmt.Println(context.Cause(ctx) == nil) // true
eg, ctx := errgroup.WithContext(ctx)
fmt.Println(context.Cause(ctx) == nil) // true
for i := 0; i < 10; i++ {
eg.Go(func() error {
return nil
})
}
if err := eg.Wait(); err != nil {
panic(err)
}
fmt.Println(
context.Cause(ctx) == nil, // false
errors.Is(context.Cause(ctx), context.Canceled), // true
)
}