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