package main import "fmt" import "time" func source(dst chan int) { for k := 1; k <= 100000; k++ { dst <- k*(k + 1)/2 } close(dst) } func makePairs(src chan int, dst chan [2]int) { var v1, v2 int var ok1, ok2 bool for { v1, ok1 = <-src v2, ok2 = <-src if !(ok1 && ok2) { break } dst <- [2]int{v1, v2} } close(dst) } func split(src chan [2]int, dst1 chan [2]int, dst2 chan [2]int) { for chunk := range src { dst1 <- chunk dst2 <- chunk } close(dst1) close(dst2) } func multiply(src chan [2]int, dst chan int) { for chunk := range src { dst <- chunk[0]*chunk[1] } close(dst) } func gcd(src chan [2]int, dst chan int) { var helper func(int, int) helper = func(x int, y int) { if x < y { helper(y, x) } else if y == 0 { dst <- x } else { helper(y, x % y) } } for chunk := range src { helper(chunk[0], chunk[1]) } close(dst) } func combine(src1 chan int, src2 chan int, dst chan [2]int) { var v1, v2 int var ok1, ok2 bool for { v1, ok1 = <-src1 v2, ok2 = <-src2 if !(ok1 && ok2) { break } dst <- [2]int{v1, v2} } close(dst) } func divide(src chan [2]int, dst chan int) { for chunk := range src { dst <- chunk[0]/chunk[1] } close(dst) } func getDigits(src chan int, dst chan int) { var helper func(int) helper = func(x int) { if x != 0 { helper(x/10) dst <- x % 10 } } for chunk := range src { helper(chunk) } close(dst) } func sink(src chan int) { for _ = range src { } } func pipeline() { // Channels are unbuffered for a fair comparison with generators c1 := make(chan int) c2 := make(chan [2]int) c3 := make(chan [2]int) c4 := make(chan [2]int) c5 := make(chan int) c6 := make(chan int) c7 := make(chan [2]int) c8 := make(chan int) c9 := make(chan int) go source(c1) go makePairs(c1, c2) go split(c2, c3, c4) go multiply(c3, c5) go gcd(c4, c6) go combine(c5, c6, c7) go divide(c7, c8) go getDigits(c8, c9) sink(c9) } func main() { timer := time.Now() for i := 0; i < 100; i++ { pipeline() } fmt.Println(time.Now().Sub(timer)) }