等待缓冲通道满

时间:2016-08-05 16:07:19

标签: go

我一定错过了一些东西,因为我还没有在网上找到这个基本问题的答案。我正在使用一个能够保存三个int值的缓冲通道。

然后我使用三个goroutine来填充它,并且我想在缓冲通道已满后进行操作。

以下是解释问题的摘录:

func main() {
    // Initialization of the slice a and 0 < n < len(a) - 1.
    difs := make(chan int, 3)
    go routine(a[:n], difs)
    go routine(a[n + 1:], difs)
    go routine(a[n - 1:n + 1], difs)

    fmt.Println(<-difs) // Display the first result returned by one of the routine.
}

func routine(a []int, out chan<- int) {
    // Long computation.
    out <- result
}

我想更新我的代码,以便fmt.Println(<-difs)在计算完所有值后显示int数组。我可以使用三次<-difs但是我想知道Go是否提供了更清洁的东西。

2 个答案:

答案 0 :(得分:5)

函数len()支持通道,返回通道中未读排队元素的数量。但是,您必须运行循环以定期检查它。

传统的处理方法是使用sync.WaitGroup,因为:

func main() {
    // Initialization of the slice a and 0 < n < len(a) - 1.
    var wg sync.WaitGroup
    wg.Add(3)
    difs := make(chan int, 3)
    go routine(a[:n], difs, &wg)
    go routine(a[n + 1:], difs, &wg)
    go routine(n - 1:n + 1], difs, &wg)

    wg.Wait() // blocks until wg.Done() is called 3 times
    fmt.Println(<-difs) // Display the first result returned by one of the routine.
}

// NOTE: This MUST accept a POINTER to the waitgroup.  They are not copy-safe.
func routine(a []int, out chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    // Long computation.
    out <- result
}

答案 1 :(得分:5)

等待使用频道本身,就像这个工作示例代码:

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} // Initialization of the slice a and 0 < n < len(a) - 1.
    difs := make(chan int, 3)

    go routine(a[0:4], difs)
    go routine(a[4:8], difs)
    go routine(a[8:12], difs)

    result := []int{<-difs, <-difs, <-difs}

    fmt.Println(result) // Display the first result returned by one of the routine.
}

func routine(a []int, out chan<- int) {
    result := 0 // Long computation.
    for _, v := range a {
        result += v
    }
    out <- result
}

输出:

[10 42 26]