I am a golang newbie who is trying to understand the correct design pattern for this problem. My current solution seems very verbose, and I'm not sure what the better approach would be.
I am trying to design a system that:
- executes N goroutines
- returns the result of each goroutine as soon as it is available
- if a goroutine returns a particular value, it should kill other goroutines will cancel.
The goal: I want to kick off a number of goroutines, but I want to cancel the routines if one routine returns a particular result.
I'm trying to understand if my code is super "smelly" or if this is the prescribed way of doing things. I still don't have a great feeling for go, so any help would be appreciated.
Here is what I've written:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
fooCheck := make(chan bool)
barCheck := make(chan bool)
go foo(ctx, 3000, fooCheck)
go bar(ctx, 5000, barCheck)
for fooCheck != nil ||
barCheck != nil {
select {
case res, ok := <-fooCheck:
if !ok {
fooCheck = nil
continue
}
if res == false {
cancel()
}
fmt.Printf("result of foocheck: %t
", res)
case res, ok := <-barCheck:
if !ok {
barCheck = nil
continue
}
fmt.Printf("result of barcheck: %t
", res)
}
}
fmt.Printf("here we are at the end of the loop, ready to do some more processing...")
}
func foo(ctx context.Context, pretendWorkTime int, in chan<- bool) {
fmt.Printf("simulate doing foo work and pass ctx down to cancel down the calltree
")
time.Sleep(time.Millisecond * time.Duration(pretendWorkTime))
select {
case <-ctx.Done():
fmt.Printf("
We cancelled this operation!
")
break
default:
fmt.Printf("we have done some foo work!
")
in <- false
}
close(in)
}
func bar(ctx context.Context, pretendWorkTime int, in chan<- bool) {
fmt.Printf("simulate doing bar work and pass ctx down to cancel down the calltree
")
time.Sleep(time.Millisecond * time.Duration(pretendWorkTime))
select {
case <-ctx.Done():
fmt.Printf("
We cancelled the bar operation!
")
break
default:
fmt.Printf("we have done some bar work!
")
in <- true
}
close(in)
}
(play with the code here: https://play.golang.org/p/HAA-LIxWNt0)
The output works as expected, but I'm afraid I'm making some decision which will blow off my foot later.