一个接收通道并将字符串发送到通道的goroutine。

huangapple go评论102阅读模式
英文:

goroutine that takes a channel receiver and sends string to channel

问题

我正在尝试创建一个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
        }
    }

    // 继续使用 'str',它现在包含了从 'strReceiver' 通道附加的值
}

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

    var val string
    // 使用 'item' 做一些操作,并设置 'val'...

    receiver <- val
}
英文:

I am trying to make a loop of goroutines that take a channel that receives strings, and every time it is received it should append the value to another string. Only at the end of all goroutines (the goroutine count should be the length of the list passed in), should the code continue on.

My example below doesn't seem to append the values from the strReceiver channel onto str, because str is never modified.

Anyone know what's wrong?

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, &amp;currProc)
			str += &lt;-strReceiver 
		}()
	}

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

	// continue on using &#39;str&#39; which now contains the append values from the &#39;strReceiver&#39; channel
}

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

    var val string
	// do something with &#39;item&#39; and set &#39;val&#39;...

	receiver &lt;- val
}

答案1

得分: 3

你的代码存在一个问题,就是在你的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)
}
英文:

One problem with your code is that the closure around your go routine invocation is too big.

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

item is scoped to the for loop, not the anonymous function in your goroutine, so while you firing off N goroutines, your item variable meanwhile is being updated in a for loop. To remedy this, pass the variable to your goroutine explicitly, to avoid using a closure:

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

huangapple
  • 本文由 发表于 2017年4月23日 23:20:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/43572928.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定