对 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协程:

  1. Input 通道作为参数指定为 in 通道。
  2. 在for循环中,执行了第一个printf。
  3. in 通道的值分配给变量 input
  4. 执行最后一个 printf 以显示 thisID 和 input 的值。(直到其他 Goroutines 运行 之后才真正执行)。

发布者协程:

  1. Input 通道作为参数指定为 out 通道。
  2. 在for循环中,dataID递增,然后首先执行printf。

  3. 字符串赋值给数据

  4. data的值传给out了

问题:

  1. 来自 out 的值在发布者 Goroutine 中传递到哪里?好像只是在for循环的范围内,这样不会造成死锁吧。因为这是一个无缓冲的通道。

  2. 如果 main 中的所有 Goroutines 都将参数作为通道 input

    如果一个函数的输出,我已经习惯了这样写代码 用于另一个:

    foo = fcn1(input) fcn2(foo)

我怀疑它与背景中的 Goroutines 运行 有关系,但我不确定我是否会感谢您的解释。

  1. 为什么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接收。这个 sendreceive 是通过 Go 上的特殊运算符 <- 完成的。事实上你的解释有点错误。

out <- data 获取数据并通过名为 out 的通道发送数据,直到 <- in 从该通道读取数据(记住 in 和 out 与 main 命名相同的通道)。这就是 workerProcess 和 publisher 通信的方式。

问题 3 重复。一旦 main 完成,您的整个程序就会终止(在您的情况下是 1 毫秒后。程序终止后没有任何反应。给程序更多的时间来执行。(non-printing 与通道无关)。