【问题标题】:goroutine that takes a channel receiver and sends string to channel接受通道接收器并将字符串发送到通道的 goroutine
【发布时间】:2017-09-20 05:45:41
【问题描述】:

我正在尝试创建一个 goroutine 循环,该循环采用接收字符串的通道,并且每次接收到它时都应该将值附加到另一个字符串。只有在所有 goroutine 的末尾(goroutine 计数应该是传入的 list 的长度),代码才应该继续。

我下面的示例似乎没有将来自strReceiver 通道的值附加到str,因为 str 从未被修改过。

有人知道怎么回事吗?

func appendToStr(str string, list []string, origin *url.URL) {
    var currProc int32 = 0;
    var maxProc int32 = int32(len(list))

    var strReceiver := make(chan string, len(list))
    for _, item := range list {
        go func() {
            doAsyncAndIncrement(item, strReceiver, &currProc)
            str += <-strReceiver 
        }()
    }

    for {
        if atomic.LoadInt32(&currProc) <= maxProc {
            break;
        }
    }

    // continue on using 'str' which now contains the append values from the 'strReceiver' channel
}

func doAsyncAndIncrement(item string, receiver chan<- string, count *int32) {
    defer atomic.AddInt32(count, 1)

    var val string
    // do something with 'item' and set 'val'...

    receiver <- val
}

【问题讨论】:

  • 对不起,这是我的错字。 async 函数确实应该接收该接收器。我已经更新了我的代码。
  • atomic.LoadInt32(&amp;currProc) &lt;= maxProc 这个条件不应该被否定吗? currProc 将在第一次迭代时中断,甚至在生成的 goroutine 有机会运行之前

标签: go


【解决方案1】:

您的代码的一个问题是围绕您的 go 例程调用的闭包太大。

for _, item := range list {
    go func() {
        doAsyncAndIncrement(item, strReceiver, &currProc)
        str += <-strReceiver 
    }()
}

item 的作用域是 for 循环,而不是你的 goroutine 中的匿名函数,所以当你启动 N 个 goroutine 时,你的 item 变量同时在 for 循环中被更新。为了解决这个问题,将变量显式传递给你的 goroutine,以避免使用闭包:

for _, item := range list {
    go func(item string) {
        doAsyncAndIncrement(item, strReceiver, &currProc)
        str += <-strReceiver 
    }(item)
}

【讨论】:

    猜你喜欢
    • 2015-12-31
    • 2018-09-29
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 2021-05-03
    相关资源
    最近更新 更多