スキップしてメイン コンテンツに移動

Goチャネル入門:送受信とバッファ

Goチャネル入門:送受信とバッファ

チャネルの基本

Go初心者が最初に触れる概念の一つがチャネルです。チャネルは chan 型で宣言し、make 関数で作成します。例えば、整数を送受信するチャネルは次のように定義します。

ch := make(chan int)

このチャネルはバッファなし(unbuffered)で、送信側と受信側が同時に実行されるまでブロックします。送信は ch <- 10、受信は value := <-ch で行います。送信側が <- を使って値を送ると、受信側が <- で受け取るまで両方とも待機します。

バッファ付きチャネル

バッファ付きチャネルは、make の第二引数に容量を指定することで作成できます。例えば、容量3のチャネルは次のようにします。

ch := make(chan int, 3)

この場合、送信側はバッファが満杯になるまでブロックせずに値を送信できます。受信側はバッファにデータが残っている限り、ブロックせずに受信できます。バッファ付きチャネルは通信のスループットを向上させるために有効です。

バッファのサイズは通信のパターンに合わせて調整します。例えば、データ生成が速く、処理が遅い場合は大きめのバッファを設定すると、送信側が頻繁にブロックされるのを防げます。

実践例:通信の流れ

以下は、Go初心者が実際にチャネルを使って通信を行うサンプルです。送信側(producer)と受信側(consumer)を別ゴルーチンで実行し、バッファ付きチャネルでデータをやり取りします。

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int, 5) // バッファ5

    // 送信側
    go func() {
        for i := 1; i <= 10; i++ {
            fmt.Println("送信:", i)
            ch <- i // バッファに入るのでブロックしない
            time.Sleep(100 * time.Millisecond)
        }
        close(ch) // 送信完了を通知
    }()

    // 受信側
    for v := range ch {
        fmt.Println("受信:", v)
        time.Sleep(200 * time.Millisecond) // 処理に時間がかかる
    }
    fmt.Println("通信終了")
}

この例では、送信側が10個の整数をチャネルに送ります。バッファが5つあるため、最初の5回はブロックせずに送信できます。受信側は range でチャネルを読み取り、チャネルが閉じられるまで待ちます。送信側が close(ch) を呼ぶことで、受信側はループを抜け、通信が終了します。

ポイントは、chan 型の変数を make で作成し、<- で送受信を行うことです。バッファ付きチャネルを使うと、送信側と受信側の実行タイミングを緩和でき、通信の効率が向上します。

この記事はAIによって作成されました。

コメント