我在研究围棋并发模式。
我不确定的一个模式是:黛西链https://talks.golang.org/2012/concurrency.slide#39
对我来说,很难理解代码的控制流。
有人能跟我解释一下吗?
package main
import (
"fmt"
)
func f(left, right chan int) {
left <- 1 + <-right
}
func main() {
const n = 10000
leftmost := make(chan int)
right := leftmost //point B: what does these do ?
left := leftmost
for i := 0; i < n; i++ {
right = make(chan int)
go f(left, right)
left = right //point A
}
go func(c chan int) { c <- 1 }(right)
fmt.Println(<-leftmost)
}结论
func f(left chan<- int, right <-chan int)是很好的实践,而不是上面提到的原始函数签名。原因是去通道块‘读’直到接收到的信道接收信号。
发布于 2014-10-02 11:28:29
VonC已经给出了一个直接的答案。以下是一些进一步的评论。
一个稍微整洁的版本是在操场中,不同的是作为参数传递的通道具有显式指定的方向。<-chan和chan<-.这样做是很好的做法,因为编译器可以为您捕获更多的错误。
是一种替代的、等价的程序,它有一条n大猩猩的雏菊链,可以使用一组通道来编写。这将使用较少的代码行分配相同的信道总数。请参阅游乐场
package main
import (
"fmt"
)
func f(left chan<- int, right <-chan int) {
left <- 1 + <-right
}
func main() {
const n = 10000
// first we construct an array of n+1 channels each being a 'chan int'
var channels [n+1]chan int
for i := range channels {
channels[i] = make(chan int)
}
// now we wire n goroutines in a chain
for i := 0; i < n; i++ {
go f(channels[i], channels[i+1])
}
// insert a value into the right-hand end
go func(c chan<- int) { c <- 1 }(channels[n])
// pick up the value emerging from the left-hand end
fmt.Println(<-channels[0])
}我希望你现在能看到原来的程序是如何等同于这个程序的。有一个小的区别:最初的程序不创建任何通道数组,所以使用的内存稍微少一点。
发布于 2014-10-01 06:59:45
它说明了你可以产生大量的猩猩。
在这里,每个go f(left, right)块:left <- 1 + <-right块,因为它等待right获取一个值。见"高朗频道维持秩序吗?“。
这里创建的所有通道都是未缓冲的通道。
所有10000条峡谷都被创造出来了。
B点:使用right和left声明短变量声明。
right被初始化到最左边,但这并不重要,因为它将被重新分配到for循环(right = make(chan int))中的一个新通道。
宣布权利的另一种方式是:
右陈intleft是用leftmost初始化的,这是创建的第一个通道。点A:但是一旦通道开始等待(left <- 1 + <-right),for循环就被设置为right,并创建了一个新的right:这就是雏菊链的构建方式
left <- (new) right (now left) <- (new) right (now left) <- ...然后,将一个值发送到创建的最后一个right通道:{c <- 1 }(right)
然后等待为接收其值而创建的第一个leftmost通道(递增10000倍)。
因为接收者总是阻塞直到有数据要接收,所以main()函数本身在leftmost最终接收到它的值之前不会退出。
如果main()过早退出,雏菊链就没有时间完成了。
https://stackoverflow.com/questions/26135616
复制相似问题