Go のコードレビューしてて次のようなコードに遭遇した。sem.Acquire() にわたす ctx が context.Background() になってしまっていて、WithTimeline が切れても ctx.Done にいってくれない、ということがあった。
解決策としては、 sem.Acquire() に同じ ctx を渡すだけで解決。
こういうの、わかってしまえばそれだけかってなるけど、機械的に検出することができないのが悩ましいところ。
問題のあったコード
package main import ( "context" "golang.org/x/sync/semaphore" "log" "time" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() sem := semaphore.NewWeighted(3) for { select { case <-ctx.Done(): log.Fatal("timeout.") return default: if err := sem.Acquire(context.Background(), 1); err != nil { log.Fatal(err) } log.Printf("sem acquired!") go (func() { defer sem.Release(1) time.Sleep(10*time.Second) log.Printf("go func done!") })() } } }
解決策
- if err := sem.Acquire(context.Background(), 1); err != nil { + if err := sem.Acquire(ctx, 1); err != nil {