概要
以下、自分用のメモです。
ゴルーチン(goroutine) って、とても便利ですが、たまにリークさせてしまうことがあったりします。
基本的なパターンは決まっているのですが、見つけるのも難しいので可能な限り、そうならないように注意した方が良いですね。
送信側を忘れてしまっているパターン
package leak import ( "time" "github.com/devlights/gomy/output" ) // ForgottenSender -- goroutineリークが発生するパターンのサンプルです。 // // チャネルを作成し、チャネルの送信側がいないパターン。 // 受信側のgoroutineが永遠に待ち続けるので終了しません。 // // 解決方法としては、送信側が適切に使い終わったチャネルを閉じること。 // // REFERENCES: // - https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee func ForgottenSender() error { var ( fn = func(ch <-chan int) { data := <-ch output.Stdoutl("[goroutine leak]", data) } ch = make(chan int) ) go fn(ch) // // チャネルにデータを送信するものがいないので // 上のgoroutineはプロセスが起動中は永遠に終了しません。 // time.Sleep(1 * time.Second) return nil }
受信側を忘れてしまっているパターン
package leak import ( "time" "github.com/devlights/gomy/output" ) // ForgottenReceiver -- goroutineリークが発生するパターンのサンプルです。 // // チャネルを作成し、チャネルの受信側がいないパターン。 // 送信側のgoroutineが永遠に待ち続けるので終了しません。 // // 解決方法としては、Bufferedなチャネルを使うこと。 // // REFERENCES: // - https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee func ForgottenReceiver() error { var ( fn = func(ch chan<- int) { ch <- 1 output.Stdoutl("[goroutine leak]", 1) } ch = make(chan int) ) go fn(ch) // // チャネルのデータを受信するものがいないので // 上の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
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。