これまで、チャネルを使った例をいくつか見てきたけど、今回はもうちょっと意味のあるデータを通信してみる。
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 回繰り返したら ch に nil を送って終了する。
receiveColor はチャネル ch から Req が送られてきたら、その色名を出力してから返信用のチャネル Req.Reply に 0 を送信する。これは処理が完了したことを知らせるだけなので、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