チャネルを使ってデータ交換

これまで、チャネルを使った例をいくつか見てきたけど、今回はもうちょっと意味のあるデータを通信してみる。

package main

import (
    "fmt"
)

type Req struct {
    Color string
    Reply chan<- int
}

func newReq(color string, ch chan int) *Req {
    req := new(Req)
    req.Color = color
    req.Reply = ch
    return req
}

func sendColor(n int, color string, ch chan<- *Req) {
    in := make(chan int)
    v := newReq(color, in)
    for ; n > 0; n-- {
        ch <- v <- in
    }
    ch <- nil
}

func receiveColor(n int, ch <-chan *Req) {
    for n > 0 {
        req := <- ch
        if req == nil {
            n--
        } else {
            fmt.Println(req.Color)
            req.Reply <- 0
        }
    }
}

func main() {
    ch := make(chan *Req)
    go sendColor(8, "red", ch)
    go sendColor(7, "green", ch)
    go sendColor(6, "blue", ch)
    receiveColor(3, ch)
}

ゴルーチンで起動される関数 sendColor は送信用のチャネル ch に、色名(文字列)と返信用のチャネルをまとめた Req 構造体を送信する。で、それを n 回繰り返したら chnil を送って終了する。
receiveColor はチャネル ch から Req が送られてきたら、その色名を出力してから返信用のチャネル Req.Reply0 を送信する。これは処理が完了したことを知らせるだけなので、0 でなくても int なら何でもいい。で、それを n がゼロになるまで繰り返す。この n は起動されたゴルーチンの数だ。

では、実行例。

^o^ > go run channel_color.go
blue
red
green
blue
red
green
blue
red
green
blue
red
green
blue
red
green
blue
red
green
red
green
red

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.