英文:
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, &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
}
答案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, &currProc)
str += <-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, &currProc)
str += <-strReceiver
}(item)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论