いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-271 (ゴルーチンリークが発生するパターン (1))(送信側、受信側を忘れてしまう)

概要

以下、自分用のメモです。

ゴルーチン(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

Go言語による並行処理

Go言語による並行処理

Amazon


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。