Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

goroutine that takes a channel receiver and sends string to channel

Tags:

go

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
}
like image 314
Lansana Camara Avatar asked Oct 18 '22 13:10

Lansana Camara


1 Answers

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)
}
like image 124
Flimzy Avatar answered Nov 14 '22 01:11

Flimzy