技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

channel【Go】

channelを使って、goroutineと関数の間で、データをやり取りすることができます。

次の例では、スライスの中身を足し合わせた結果を、channelを使って返却します。

func useChannel(s []int, c chan int) {
    var sum int
    for _, v := range s {
        sum += v
    }
    c <- sum    // sumをchannelに入れて返却
}

func main() {
    s := []int{2, 3, 7, 8}
    c := make(chan int)    // channelはint型を指定(サイズを指定しないunbuffered channel。デフォルトでサイズは0)
    go useChannelS(s, c)
    x := <-c    // 返ってきたchannelを受け取る
    fmt.Println(x)    // 20
}

goroutineの処理の後に記述した、channelの中身を変数に格納する処理

x := <-c 

は、後続の処理をブロッキングするため、sync.WaitGroup.Wait()などは必要ありません。

上記例では、最終的な合計結果(sum)をchannelに渡していますが、
close(channel)と,channelからの送信の際にfor文を用いると、
途中経過を出力することができます。

func useChannel(s []int, c chan int) {
    var sum int
    for _, v := range s {
        sum += v
        c <- sum    // 毎回sumを受信
    }
    close(c)    // forループから抜けたらcloseすることで、cをrangeで回す際の終点を知らせる
}

func main() {
    s := []int{2, 3, 8, 9, 12}
    c := make(chan int, len(s))    // 第2引数を指定して、あらかじめ容量を確保
    go useChannel(s, c)
    for i := range c {
        fmt.Println(i)    // 受信の都度出力
    }
}


もちろん、channelの型はint以外にも対応します。
stringの例です。

func useChannelS(s string, c chan string) {
    c <- s + "を受け取りましたので返します。"
}

func main() {
    c2 := make(chan string)
    go useChannelS("A", c2)
    xx := <-c2
    fmt.Println(xx)    // Aを受け取りましたので返します。
}


channelをinterface型にしてswitch typeを使えば、任意の型を指定することができます。

func interfaceChannel(i interface{}, c chan interface{}) {
    var rv interface{}
    switch ii := i.(type) {
    case string:
        rv = ii + "ですね"
    case int:
        rv = ii + 100
    default:
        rv = "undefined"
    }
    c <- rv
}

func main() {
    // crypto/randパッケージを使用した乱数生成
    seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
    rand.Seed(seed.Int64())

    rn := rand.Int63() % 2

    var i interface{}

    if rn == 0 {
        i = 13
    } else {
        i = "あかさたな"
    }

    c3 := make(chan interface{})
    go interfaceChannel(i, c3)
    xxx := <-c3
    fmt.Println(xxx)
}


channelに関する、実に様々なパターンが記述されています。
hori-ryota.com