Allows the done/select channel pattern to be extracted out into another function that handles done notification using a separate go routine and a relay stream. Clients now do not need to implement the select/done channel, they instead range over the relay stream that is returned from the newly defined function orDone.
Here is the example code:
func main() {
var wg sync.WaitGroup
cows := make(chan interface{}, 10)
done := make(chan interface{}, 10)
wg.Add(1)
go consumeCows(&wg, done, cows)
}
func consumeCows(wg *sync.WaitGroup, done, cows <-chan interface{}) {
defer wg.Done()
for cow := range orDone(done, cows) {
fmt.Printf("%v\n", cow)
}
}
func orDone(done, c <-chan interface{}) <-chan interface{} {
relayCh := make(chan interface{})
go func() {
defer close(relayCh)
for {
select {
case <-done:
return
case v, ok := <-c:
if !ok {
return
}
select {
case relayCh <- v:
case <-done:
return
}
}
}
}()
return relayCh
}
found on youtube learn the Go concurrency pattern that blew my mind (by Kantan Coding) (Not sure if this is applicable to anything in lorax, I just wanted somewhere to record the act that I saw this useful concurrency design pattern)
Allows the done/select channel pattern to be extracted out into another function that handles done notification using a separate go routine and a relay stream. Clients now do not need to implement the select/done channel, they instead range over the relay stream that is returned from the newly defined function orDone.
Here is the example code:
Also see: Go Concurrency Patterns: Pipelines and cancellation by Sameer Ajmani (13-mar-2014)