チャネル(channel)の使い方

Goのチャネル(channel)は、複数のGoroutine間でデータをやり取りするための仕組みです。Goの並行処理において、チャネルは「Goroutine間の通信手段」として非常に重要な役割を果たします。ここでは、チャネルの基本的な使い方と関連概念について詳しく説明します。


1. チャネルの概要

チャネルは、**送信(send)受信(receive)**という2つの操作によってデータのやり取りを行います。

  • チャネルはchanキーワードを使って作成します。

  • 同じ型のデータしか送受信できません。

  • チャネルの送受信はデフォルトではブロッキング動作です(片方が準備できるまで待機)。


2. チャネルの宣言と作成

go
ch := make(chan int) // int型のチャネルを作成

3. チャネルへの送信と受信

go
// 送信(send) ch <- 42 // 受信(receive) value := <-ch

このとき、送信側と受信側のどちらか一方が準備できていないと、もう一方は待機します


4. Goroutineと組み合わせた基本例

go
package main import ( "fmt" ) func worker(ch chan string) { ch <- "Hello from Goroutine" } func main() { ch := make(chan string) go worker(ch) // 新しいGoroutineを起動 message := <-ch // チャネルから受信(ブロックされる) fmt.Println(message) // 結果: Hello from Goroutine }

この例では、worker関数が別のGoroutineとして実行され、チャネルを通じてメッセージを送信しています。


5. バッファ付きチャネル

バッファ付きチャネルを使うと、一定数の値をチャネルに非同期に送信できます。

go
ch := make(chan int, 2) // バッファサイズ2 ch <- 1 // 非ブロッキング ch <- 2 // 非ブロッキング // ch <- 3 // ここでブロックされる(バッファが満杯)

6. チャネルのクローズ

チャネルを閉じると、それ以降送信はできなくなり、受信側ではrange文や多値受信で検知できます。

go
close(ch)
go
for val := range ch { fmt.Println(val) }

7. select文を使った複数チャネルの監視

select文を使うと、複数のチャネルからのデータを待つことができます。

go
select { case msg1 := <-ch1: fmt.Println("ch1から受信:", msg1) case msg2 := <-ch2: fmt.Println("ch2から受信:", msg2) default: fmt.Println("どのチャネルも準備できていません") }

8. チャネルの注意点

  • クローズされたチャネルに対して送信しようとするとランタイムパニックになります。

  • 読み取りはクローズ後でも可能で、値はそのまま読み取れますが、falseのフラグが返されます。

go
val, ok := <-ch if !ok { fmt.Println("チャネルが閉じられました") }

まとめ

概要 内容
チャネル作成 make(chan 型)
送信 ch <- 値
受信 値 := <-ch
バッファ付き make(chan 型, バッファサイズ)
クローズ close(ch)
複数監視 select

チャネルはGoの並行処理において、Goroutine間の安全で効率的な通信手段を提供します。正しく使うことで、ロックを使わずにスレッドセーフな設計を実現できます。

生成日:2025/05/03