タスクを複数のgoroutineに分割して、順序通りに処理させたい場合に利用します。
fan-inは、複数の入力を1つのchannelにまとめて受信するパターンです。
fan-outは、複数の関数(goroutine)が、1つのchannelから値を読み取り送信するパターンです。
fan-outはCPUに作業を分配するため、Workersパターンとも呼ばれます。
次の例では、producerとmulti2とmulti4、main関数をchannelを通して接続し、
複数の処理を並行に、かつタスク分割して順々に実行しています。
処理が終わったchannelは、closeしないとrangeループから抜けられずに、
deadlockを引き起こすため、注意が必要です。
func producer(first chan<- int) { // firstは送信専用
defer close(first) // closeしないとrageループがdeadlockを引き起こす
for i := 0; i < 10; i++ {
first <- i
}
}
func multi2(first <-chan int, second chan<- int) { // firstは受信専用、secondは送信専用
defer close(second) // closeしないとrageループがdeadlockを引き起こす
for v := range first {
second <- v * 2
}
}
func multi4(second <-chan int, third chan<- int) { // secondは受信専用、thirdは送信専用
defer close(third) // closeしないとrageループがdeadlockを引き起こす
for v := range second {
third <- v * 4
}
}
func main() {
first := make(chan int)
second := make(chan int)
third := make(chan int)
go producer(first)
go multi2(first, second)
go multi4(second, third)
for v := range third {
fmt.Println(v)
}
}
上記コードのなかで、func定義のchannel引数に「<-」が記載されていますが、
これによって、対象のchannelを、送受信どちらかの専用とすることができます。
1行見ただけで、そのchannelが何のためのchannelなのか分かるようになり、
コードの保守性が向上します。
このパターンに基づいて、処理を分割して開発することができれば、
メンテナンスのしやすさや、コードのわかりやすさにもつながるかと思います。
ゴルーチン、チャネルを利用した並行パターン / fujimisakari blog