概要
以下、自分用のメモです。
ゴルーチン(goroutine) って、とても便利ですが、たまにリークさせてしまうことがあったりします。
基本的なパターンは決まっているのですが、見つけるのも難しいので可能な限り、そうならないように注意した方が良いですね。
送信しようとしているが受信側がいなくなってしまうパターン
package leak import ( "context" "time" "github.com/devlights/gomy/output" ) // AbandonedSender -- goroutineリークが発生するパターンのサンプルです。 // // チャネルの送受信の実装があるが、タイミングによっては受信側がいなくなってしまうパターン。 // 送信側のgoroutineが永遠に待ち続けるので終了しません。 // // 解決方法としては、Bufferedなチャネルを使うこと。 // // REFERENCES: // - https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee func AbandonedSender() error { var ( ctx, cxl = context.WithTimeout(context.Background(), 10*time.Millisecond) ch = make(chan int) iowait = func() { time.Sleep(1 * time.Second) } fn = func(ch chan<- int) { iowait() ch <- 1 output.Stdoutl("[send]", 1) } ) defer cxl() go fn(ch) select { case v := <-ch: output.Stdoutl("[recv]", v) case <-ctx.Done(): } // // チャネルからデータを受信するものがいなくなるので // 上のgoroutineはプロセスが起動中は永遠に終了しません。 // time.Sleep(1 * time.Second) return nil }
受信しようとしているが送信側がいなくなってしまうパターン
package leak import ( "context" "time" "github.com/devlights/gomy/output" ) // AbandonedReceiver -- goroutineリークが発生するパターンのサンプルです。 // // チャネルの送受信の実装があるが、タイミングによっては送信側がいなくなってしまうパターン。 // 受信側のgoroutineが永遠に待ち続けるので終了しません。 // // 解決方法としては、送信側が適切に使い終わったチャネルを閉じること。 // // REFERENCES: // - https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee func AbandonedReceiver() error { var ( ctx, cxl = context.WithTimeout(context.Background(), 10*time.Millisecond) ch = make(chan int) iowait = func() { time.Sleep(1 * time.Second) } fn = func(ch <-chan int) { iowait() data := <-ch output.Stdoutl("[recv]", data) } ) defer cxl() go fn(ch) select { case ch <- 1: output.Stdoutl("[send]", 1) case <-ctx.Done(): } // // チャネルにデータを送信するものがいなくなるので // 上のgoroutineはプロセスが起動中は永遠に終了しません。 // time.Sleep(1 * time.Second) return nil }
参考情報
https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee
try-golang/examples/basic/goroutines/leak at master · devlights/try-golang · GitHub
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。