14.12. 链式操作
下面的演示程序 chaining.go 再次演示了启动大量的协程是多么的容易。它发生在 main 函数的 for 循环中。在循环之后,向 rightmost 通道中插入 0 ,在不到 1.5 s 的时间执行了100000 个协程,并将结果 100000 打印。
这个程序还演示了如何通过命令行的参数定义一个协程的数量,并通过 flag.Int 解析,例如: chaining -n=7000
(编译后通过命令行执行),可以生成 7000 个协程。
示例 14.17 - chaining.go:
package main
import (
"flag"
"fmt"
)
var ngoroutine = flag.Int("n", 100000, "how many goroutines")
func f(left, right chan int) { left <- 1+<-right }
func main() {
flag.Parse()
leftmost := make(chan int)
var left, right chan int = nil, leftmost
for i := 0; i < *ngoroutine; i++ {
left, right = right, make(chan int)
go f(left, right)
}
right <- 0
// start the chaining 开始链接
x := <-leftmost // wait for completion 等待完成
fmt.Println(x)
// 结果: 100000 , 大约 1,5s (我实际测试只用了不到200ms)
}
译者注:上面的例子变量名以及一些 golang 语法特性的使用不利于刚学习的同学理解 channel 的特性,下面是热心网友投稿,稍微优化了一下变量命名和语法并添加了必要的注释,从而能够帮助更加专注的理解 channel 语法的特性, 仅供参考,不一定对每位同学都有帮助!
package main
import (
"flag"
"fmt"
)
var ngoroutine = flag.Int("n", 100000, "how many goroutines")
// last 相当于上一个的意思
func f(last, current chan int) {
temp := 1 + <-current // 当 current 没有值时,这里会被阻塞
last <- temp
}
func main() {
first := make(chan int)
last := first
for i := 0; i < *ngoroutine; i++ {
current := make(chan int)
// 将上一次循环创建的 chan,和本次循环的 chan 一起交给函数, 函数会帮我们完成 last <- 1+ <- curr 的过程
go f(last, current)
// 记录本次循环中的 right,给下一次循环创建使用
last = current
}
// 开始链接
last <- 0
x := <-first // wait for completion 等待完成
fmt.Println(x)
// 结果: 100000 , 大约 1,5s (我实际测试只用了不到200ms)
}
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。