对 Goroutines 的通道参数感到困惑
Confused about channel argument for Goroutines
我正在学习 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协程:
- Input 通道作为参数指定为 in 通道。
- 在for循环中,执行了第一个printf。
- in 通道的值分配给变量 input。
- 执行最后一个 printf 以显示 thisID 和 input 的值。(直到其他 Goroutines 运行 之后才真正执行)。
发布者协程:
- Input 通道作为参数指定为 out 通道。
在for循环中,dataID递增,然后首先执行printf。
字符串赋值给数据
data的值传给out了
问题:
来自 out 的值在发布者 Goroutine 中传递到哪里?好像只是在for循环的范围内,这样不会造成死锁吧。因为这是一个无缓冲的通道。
如果
main 中的所有 Goroutines 都将参数作为通道 input。
如果一个函数的输出,我已经习惯了这样写代码
用于另一个:
foo = fcn1(input)
fcn2(foo)
我怀疑它与背景中的 Goroutines 运行 有关系,但我不确定我是否会感谢您的解释。
- 为什么workerProcess中的最后一个printf语句没有执行?我的猜测是通道是空的,所以它正在等待一个值。
部分输出:
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..
你有一个频道,它是用make
在主频道制作的。
这个单一通道在 workerProcess 中命名为 in
,在 publisher 中命名为 out
。 out 是 publisher 的函数参数,它回答了问题 1。
问题 2:这就是频道的全部目的。您在通道的输入端塞入通道的内容会在其输出端输出。如果一个函数引用了这样一个通道(的一端),它可能会与引用相同通道(它的另一端)的其他人进行通信。生产者发送到通道的内容被workerProcess接收。这个 send 和 receive 是通过 Go 上的特殊运算符 <-
完成的。事实上你的解释有点错误。
out <- data
获取数据并通过名为 out 的通道发送数据,直到 <- in
从该通道读取数据(记住 in 和 out 与 main 命名相同的通道)。这就是 workerProcess 和 publisher 通信的方式。
问题 3 重复。一旦 main 完成,您的整个程序就会终止(在您的情况下是 1 毫秒后。程序终止后没有任何反应。给程序更多的时间来执行。(non-printing 与通道无关)。
我正在学习 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协程:
- Input 通道作为参数指定为 in 通道。
- 在for循环中,执行了第一个printf。
- in 通道的值分配给变量 input。
- 执行最后一个 printf 以显示 thisID 和 input 的值。(直到其他 Goroutines 运行 之后才真正执行)。
发布者协程:
- Input 通道作为参数指定为 out 通道。
在for循环中,dataID递增,然后首先执行printf。
字符串赋值给数据
data的值传给out了
问题:
来自 out 的值在发布者 Goroutine 中传递到哪里?好像只是在for循环的范围内,这样不会造成死锁吧。因为这是一个无缓冲的通道。
如果 main 中的所有 Goroutines 都将参数作为通道 input。
如果一个函数的输出,我已经习惯了这样写代码 用于另一个:
foo = fcn1(input) fcn2(foo)
我怀疑它与背景中的 Goroutines 运行 有关系,但我不确定我是否会感谢您的解释。
- 为什么workerProcess中的最后一个printf语句没有执行?我的猜测是通道是空的,所以它正在等待一个值。
部分输出:
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..
你有一个频道,它是用make
在主频道制作的。
这个单一通道在 workerProcess 中命名为 in
,在 publisher 中命名为 out
。 out 是 publisher 的函数参数,它回答了问题 1。
问题 2:这就是频道的全部目的。您在通道的输入端塞入通道的内容会在其输出端输出。如果一个函数引用了这样一个通道(的一端),它可能会与引用相同通道(它的另一端)的其他人进行通信。生产者发送到通道的内容被workerProcess接收。这个 send 和 receive 是通过 Go 上的特殊运算符 <-
完成的。事实上你的解释有点错误。
out <- data
获取数据并通过名为 out 的通道发送数据,直到 <- in
从该通道读取数据(记住 in 和 out 与 main 命名相同的通道)。这就是 workerProcess 和 publisher 通信的方式。
问题 3 重复。一旦 main 完成,您的整个程序就会终止(在您的情况下是 1 毫秒后。程序终止后没有任何反应。给程序更多的时间来执行。(non-printing 与通道无关)。