I need to run a function multiple times in parallel.
If even once the functions returns true
(sends true
on the channel) then the final result should be true
.
How do I achieve this using goroutines and channels?
// Some performance intensive function
func foo(i int, c chan bool) {
// do some processing and return either true or false
c <- true // or false
}
func main() {
flg := false
ch := make(chan bool)
for i := 0; i < 10; i++ {
go foo(i, ch)
}
// If even once foo() returned true then val should be true
flg = flg || <-ch
}
You only receive one value from the channel (which will be the value sent by one of the foo()
calls, unpredictable which of the many), but you want to receive all.
So use a for
loop to receive as many values as you send (sent) on it:
for i := 0; i < 10; i++ {
flg = flg || <-ch
}
Although in your case it would be enough to loop until one true
value is received, as that will determine the final value of flg
, but it is still recommended to receive all values else the remaining goroutines will be blocked (as ch
is an unbuffered channel). In this example it does not matter, but in a "real-life" application it would cause goroutines to stuck forever (memory-leak).
If you don't want to wait for all foo()
calls to complete and return as soon as possible (as soon as one true
value is encountered), an option is to make ch
buffered, so all goroutines can send values on it without getting blocked. And this way you are not required to receive (and thus wait for) all the foo()
calls to complete:
ch := make(chan bool, 10)
for i := 0; i < 10; i++ {
go foo(i, ch)
}
flg := false
for i := 0; i < 10; i++ {
if <-ch {
flg = true
break
}
}
Choosing this approach, you should provide means to cancel goroutines whose work is no longer needed to avoid unnecessary CPU (and memory) usage. context.Context
is such a mean, read more about it here: Close multiple goroutine if an error occurs in one in go.