0

我有一个循环抛出多个 go 例程,它们调用一个函数,使 http 获取请求并计算和对象。

我想恢复所有这些例程的结果。我尝试使用频道,但嘿是空的,即使我强制等待所有例程完成。

这是启动例程的代码:

func main() {
    pairs := getPairs() //Returns an array of strings
    c := make(chan result)
    for _, product := range pairs {
        go getScore(product.Symbol, 1, c)
    }
    fmt.Println(len(c))
    time.Sleep(5000 * time.Millisecond)
    fmt.Println(len(c))
}

在 getScore() 结束时,我执行此操作, c 是函数中通道的名称, res 是函数的结果

c <- res

两个打印中的通道长度均为 0。

获得函数结果的最佳方法是什么?

4

2 回答 2

0
c := make(chan result)

创建一个无缓冲的通道。因此发送语句,例如

c <- res

在另一个 goroutine 尝试接收操作之前无法继续。

换句话说,在你的主 goroutine 中执行接收操作的数量与将要从其他 goroutine 尝试的发送数量相匹配。像这样:

for _, product := range pairs {
    go getScore(product.Symbol, 1, c)
}
for x := 0; x < len(pairs); x++ {
    fmt.Println(<-c)
}

有关更多信息,请参阅有关频道的 Go Tour 部分和有关频道的 Effective Go 部分

于 2018-02-25T20:16:41.973 回答
0

通道是针对共享内存的同步原型(从简单的角度来看)。缓冲通道具有长度但不是常规通道。缓冲通道在少量情况下很有用,但不是通用方法。

只需按对或对的长度添加循环的最简单方法:

// start processing
for _, product := range pairs {
    go getScore(product.Symbol, 1, c)
}
// getting a result
for i:=0; i<len(pairs); i ++ {
    result := <-c
    // process a result value
}

或者另一种方法是在另一个灌浆中收集结果:

// result and sync variable
var (
   wait sync.WaitGroup
   result int32
) 
// start processing
for _, product := range pairs {
    wait.Add(1)
    go getScore(product.Symbol, 1, c)
    go func() {
        defer wait.Done()
        // simple accumulate or maybe more complicated actions
        atomic.AddInt32(&result, <-c)
    }()
}
// wait finishing
wait.Wait()
于 2018-02-25T20:21:38.003 回答