我正在通过Go Concurrency Patterns: Pipelines and cancellation阅读/工作,但是在理解停止简短部分时遇到了麻烦。我们具有以下功能:

func sq(in <-chan int) <-chan int {
    out := make(chan int)
    go func() {
        for n := range in {
            out <- n * n
        }
        close(out)
    }()
    return out
}

func gen(nums ...int) <-chan int {
    out := make(chan int)
    go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()
    return out
}
func merge(cs ...<-chan int) <-chan int {
    var wg sync.WaitGroup
    out := make(chan int, 1) // enough space for the unread inputs

    // Start an output goroutine for each input channel in cs.  output
    // copies values from c to out until c is closed, then calls wg.Done.
    output := func(c <-chan int) {
        for n := range c {
            out <- n
        }
        wg.Done()
    }
    wg.Add(len(cs))
    for _, c := range cs {
        go output(c)
    }

    // Start a goroutine to close out once all the output goroutines are
    // done.  This must start after the wg.Add call.
    go func() {
        wg.Wait()
        close(out)
    }()
    return out
}

func main() {
    in := gen(2, 3)

    // Distribute the sq work across two goroutines that both read from in.
    c1 := sq(in)
    c2 := sq(in)

    // Consume the first value from output.
    out := merge(c1, c2)
    fmt.Println(<-out) // 4 or 9
    return
    // Apparently if we had not set the merge out buffer size to 1
    // then we would have a hanging go routine.
}

现在,如果您注意到2中的merge行,它说我们制作了chan大小为1的out buffer,因为这对于未读的输入来说是足够的空间。但是,我几乎肯定我们应该分配一个chan大小为2的buffer。根据此代码示例:
c := make(chan int, 2) // buffer size 2
c <- 1  // succeeds immediately
c <- 2  // succeeds immediately
c <- 3  // blocks until another goroutine does <-c and receives 1

因为此部分暗示chan大小为3的buffer不会被阻塞。谁能澄清/帮助我理解?

最佳答案

该程序将两个值发送到out通道,并从out通道读取一个值。不会接收到其中一个值。

如果通道未缓冲(容量0),则发送的goroutine之一将阻塞,直到程序退出。这是泄漏。

如果创建的通道容量为1,则两个goroutine都可以发送到该通道并退出。发送到通道的第一个值由main接收。第二个值保留在通道中。

如果main函数未从out通道接收值,则需要一个容量为2的通道,以防止goroutine无限期阻塞。

关于go - Goroutines channel 和“止损”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34583722/

10-16 06:39