管道模式就是将前面程序的输出数据作为输入数据传递给后面的程序。
在 Go 中管道模式被实现成了由 channel 连接的一条“数据流水线”。该流水线中,每个数据处理环节都由一组相同功能的 goroutine 完成。
在每个数据处理环节,goroutine 都要从数据输入 channel 获取前一个环节生产的数据,然后对这些数据进行处理,并将处理后的结果数据通过数据输出 channel 发往下一个环节。
func spawnNum(start, count int) <-chan int {
c := make(chan int)
go func() {
defer close(c)
for i := start; i < start+count; i++ {
c <- i
}
}()
return c
}
func filterOdd(in int) (int, bool) {
if in%2 != 0 {
return 0, false
}
return in, true
}
func square(in int) (int, bool) {
return in * in, true
}
func spawn(f func(int) (int, bool), in <-chan int) <-chan int {
out := make(chan int)
go func() {
for v := range in {
r, ok := f(v)
if ok {
out <- r
}
}
close(out)
}()
return out
}
func main() {
in := spawnNum(1, 10)
out := spawn(square, spawn(filterOdd, in))
for v := range out {
fmt.Println(v)
}
}
// Output:
// 4
// 16
// 36
// 64
// 100
这条流水线管道可以被称为“偶数的平方”。我们看到这条流水线管道有四个处理环节:
第一个环节就是生成最初的数据流;第二个环节是从序列中过滤奇数;第三个环节是将序列中的数据进行平方运算处理;第四个环节是将序列中的数据输出到控制台(console)。