Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

channel

channelはgoroutine間でデータを安全にやり取りするための仕組みです。送信と受信の操作で同期が取られるため、ミューテックスなしでgoroutine間通信が実現できます。

構文
// チャネルを作成します(バッファなし)。
ch := make(chan 型)

// バッファ付きチャネルを作成します。
ch := make(chan 型, バッファサイズ)

// チャネルに値を送信します(受信されるまでブロックします)。
ch <- 値

// チャネルから値を受信します(送信されるまでブロックします)。
v := <-ch

// チャネルをクローズします(送信側がクローズします)。
close(ch)

// クローズ済みか判定しながら受信します。
v, ok := <-ch // ok が false なら受信完了(チャネルがクローズされています)。

// rangeでチャネルの全値を受信します(クローズまでループします)。
for v := range ch { ... }
チャネルの種類
種類概要
バッファなし(make(chan T))送信と受信が同時に発生しないとブロックします。goroutine間の同期に使用します。
バッファあり(make(chan T, n))バッファが満杯になるまで送信がブロックしません。バッファが空の状態では受信がブロックします。
送信専用(chan<- T)送信のみ可能なチャネル型です。関数の引数で送信側を制限するために使います。
受信専用(<-chan T)受信のみ可能なチャネル型です。関数の引数で受信側を制限するために使います。
サンプルコード
package main

import "fmt"

// 送信専用チャネルを引数に取る関数です。
func produce(ch chan<- int, count int) {
    for i := 0; i < count; i++ {
        ch <- i // チャネルに値を送信します。
    }
    close(ch) // 送信完了を通知するためクローズします。
}

// 受信専用チャネルを引数に取る関数です。
func consume(ch <-chan int, done chan<- bool) {
    for v := range ch { // クローズされるまで受信し続けます。
        fmt.Printf("受信: %d\n", v)
    }
    done <- true // 処理完了を通知します。
}

func main() {
    // バッファなしチャネルの例(ゴルーチン間の同期)です。
    ch := make(chan int)
    done := make(chan bool)

    go produce(ch, 5)
    go consume(ch, done)

    <-done // consumeの完了を待ちます。
    fmt.Println("---")

    // バッファ付きチャネルの例です。
    buffered := make(chan string, 3)
    buffered <- "first"  // バッファに空きがあるのでブロックしません。
    buffered <- "second"
    buffered <- "third"
    // buffered <- "fourth" // バッファが満杯のためデッドロックになります。

    fmt.Println(<-buffered) // 『first』と出力されます。
    fmt.Println(<-buffered) // 『second』と出力されます。
    fmt.Println(<-buffered) // 『third』と出力されます。

    // チャネルでgoroutineの完了を通知します。
    quit := make(chan struct{}) // 値を使わない場合はstruct{}が慣習です。
    go func() {
        fmt.Println("goroutine実行中")
        close(quit) // 完了を通知するためクローズします。
    }()
    <-quit // クローズされるまでブロックします。
    fmt.Println("goroutine完了")
}
概要

Goは「メモリを共有して通信するのではなく、通信によってメモリを共有する」という設計思想を持ちます。channelはその実現手段で、goroutine間のデータの受け渡しと同期を安全に行えます。

クローズしたチャネルへの送信はパニックを引き起こします。チャネルのクローズは必ず送信側が行い、受信側は行わないようにしてください。

複数のチャネルを同時に待ち受けるには『select』を使用してください。goroutineの起動と管理については『goroutine』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。