我正在学习Go中的频道和并发性,我对以下代码如何工作感到困惑。
package main
import (
"fmt"
"time"
"sync/atomic"
)
var workerID int64
var publisherID int64
func main() {
input := make(chan string)
go workerProcess(input)
go workerProcess(input)
go workerProcess(input)
go publisher(input)
go publisher(input)
go publisher(input)
go publisher(input)
time.Sleep(1 * time.Millisecond)
}
// publisher pushes data into a channel
func publisher(out chan string) {
atomic.AddInt64(&publisherID, 1)
thisID := atomic.LoadInt64(&publisherID)
dataID := 0
for {
dataID++
fmt.Printf("publisher %d is pushing data\n", thisID)
data := fmt.Sprintf("Data from publisher %d. Data %d", thisID, dataID)
out <- data
}
}
func workerProcess(in <-chan string) {
atomic.AddInt64(&workerID, 1)
thisID := atomic.LoadInt64(&workerID)
for {
fmt.Printf("%d: waiting for input...\n", thisID)
input := <-in
fmt.Printf("%d: input is: %s\n", thisID, input)
}
}
这是我理解的,如果我错了,请纠正我:
workerProcess Goroutine:
发布商Goroutine:
在for循环中,dataID递增,然后执行第一次printf。
该字符串已分配给数据。
将数据的值传递给out。
问题:
out 的值在发布商Goroutine中传递到哪里?它似乎只是在for循环的范围内,不会导致死锁。由于这是一个无缓冲的通道。
我不知道workerProcess如何从发布者那里获取数据 主要的所有Goroutines都将参数作为通道输入。
如果输出一个函数,我过去常常编写这样的代码 用于另一个:
foo = fcn1(input)
fcn2(foo)
我怀疑它与Goroutines如何在后台运行有关,但我不确定我会欣赏一个解释。
部分输出:
1: waiting for input...
publisher 1 is pushing data
publisher 1 is pushing data
1: input is: Data from publisher 1. Data 1
1: waiting for input...
1: input is: Data from publisher 1. Data 2
1: waiting for input...
publisher 1 is pushing data
publisher 1 is pushing data
publisher 2 is pushing data
2: waiting for input..
答案 0 :(得分:3)
您有一个频道,它在主屏幕中使用make
制作。
此单个频道在workerProcess中名为in
,在发布商中名为out
。 out是发布者的函数参数,它回答问题1。
问题2:这是频道的整个目的。你输入端输入通道的是输出端。如果一个函数引用了这样一个通道的(一端),它可以与参考同一个通道(它的另一端)的其他人通信。 workerIrocess 收到接收的生产者发送的内容。此发送和接收是通过Go上的特殊运算符<-
完成的。事实上你的解释有些不对。
out <- data
获取数据并通过名为out的通道发送数据,直到<- in
从通道读取数据(记住来自main的相同通道的进出名称)。这就是workerProcess和发布者之间的沟通方式。
问题3是重复的。一旦完成,你的整个程序就会终止(在你的情况下,1毫秒后。程序终止后没有任何反应。给程序更多的时间执行。(非打印与通道无关)。