メインコンテンツにスキップ
モジュール 7 · レッスン 2 / 5コース内の 32/50~15 min
モジュールのレッスン (2/5)

チャネル: 型付きコミュニケーション

チャネルは、次の間の通信のための慣用的なメカニズムです。 ゴルーチン。囲碁の哲学 (ロブ・パイク):

「記憶を共有することでコミュニケーションするのではなく、コミュニケーションすることで記憶を共有する。」

チャネルは 型指定された FIFO キューであり、タイプセーフで同時実行も安全です。 使用します。 go と組み合わせると、Go の主要な構成要素になります。 同時並行性。

作成、送信、受信

Go
ch := make(chan int)     // canale di int, unbuffered

go func() {
    ch <- 42             // invia (può bloccare)
}()

v := <-ch                // ricevi (può bloccare)
fmt.Println(v)           // 42

構文:

  • バッファリングの場合は make(chan T) または make(chan T, N)。
  • ch <- v が送信します。
  • v := <-ch が受信します。
  • v, ok := <-ch はフラグ付きで受信します (チャンネルが閉じていて空の場合は ok = false)。

バッファなし: ランデブー

バッファなしチャネル (容量 0) は以下をブロックします。

  • 受信者の準備が整うまで、送信者。
  • 送信者の準備が整うまで、受信者。

これは同期的な予定です。「合図」として、または保証するために役立ちます。 価値が提供されたことを意味します。

バッファリング: 最大 N 個のキュー

Go
ch := make(chan int, 3)
ch <- 1   // non blocca
ch <- 2   // non blocca
ch <- 3   // non blocca
ch <- 4   // BLOCCA: il buffer è pieno

送信者は、バッファがいっぱいの場合にのみブロックします。受信機のみ 空のとき。

近距離および遠距離向け

送信者は、値がなくなるとチャネルを閉じます。

Go
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)

for v := range ch {      // termina quando ch è chiuso E vuoto
    fmt.Println(v)
}

チャネル上の for range は、チャネルが閉じられる (そして排出される) まで繰り返されます。 「届いたものはすべて消費する」という最もきれいなパターンです。

サインの方向性

関数パラメータは方向を制限できます。

Go
func producer(out chan<- int) {   // solo invio
    out <- 1
    close(out)
}

func consumer(in <-chan int) {    // solo ricezione
    for v := range in {
        fmt.Println(v)
    }
}

chan<- T = 送信専用、<-chan T = 受信専用。双方向 チャネル chan T はどちらにも渡すことができます (暗黙的な変換)。それ 明瞭さが向上し、間違いが防止されます。

よくあるパターン(プレビュー)

  • ワーカー プール: N 個のゴルーチンが jobs <-chan T から消費され、results chan<- R に生成されます。
  • パイプライン: チャネルによって接続されたステージ。
  • 完了信号: chan struct{} チャネルが閉じられ、「停止」信号が送信されます。
Go
done := make(chan struct{})
go func() {
    <-done    // blocca finché qualcuno chiude done
    cleanup()
}()
close(done)   // segnale di stop

chan struct{} は「信号」チャネルです。ペイロードはゼロバイトで、 同期。

試してみてください

運動#go.m7.l2.e1
試行回数: 0読み込み中…

unbuffered int チャネル ch を作成し、ゴルーチンから 42 を送信し、main で受信して出力します。

エディターを読み込み中…
ヒントを表示

バッファがなければ、送信者と受信者は同期します。

3 回の試行後に解決策が利用可能になります

運動#go.m7.l2.e2
試行回数: 0読み込み中…

バッファリングされたチャネル経由で 1、2、3 を送信し、チャネルを閉じてから、すべてを for-range で出力します。

エディターを読み込み中…
ヒントを表示

チャネル上の「範囲用」は、チャネルが閉じられて排水されると終了します。

3 回の試行後に解決策が利用可能になります

Quiz#go.m7.l2.e3
準備完了

送信者が送信したが受信者の準備ができていない場合、UNBUFFERED チャネルは何をしますか?

Go
ch := make(chan int)
ch <- 1 // ?
回答の選択肢

要約

  • チャネル = 型付き FIFO キュー、ゴルーチン間では安全です。
  • バッファなし: ランデブー (送信者と受信者が同期)。
  • バッファリング: デカップリング、フル/空の場合のみブロック。
  • close(ch): 送信者のみ。 for range は閉じるまで消費されます。
  • 方向性: chan<- T (送信のみ)、<-chan T (受信のみ)。
  • 純粋な同期のための信号チャネルとしての chan struct{}。