mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-22 20:56:02 +03:00
59 lines
1.6 KiB
Go
59 lines
1.6 KiB
Go
package main
|
|
|
|
import "github.com/davecgh/go-spew/spew"
|
|
|
|
// https://medium.com/capital-one-developers/buffered-channels-in-go-what-are-they-good-for-43703871828
|
|
|
|
// One common pattern for goroutines is fan-out. When you want to apply the same data to multiple algorithms,
|
|
// you can launch a goroutine for each subtask, and then gather the data back in when they are done.
|
|
// For example, you might want to process the same data via multiple scoring algorithms and return back
|
|
// all of the scores or pull data from multiple microservices to compose a single page. A buffered channel is an
|
|
// ideal way to gather the data back from your subtasks.
|
|
|
|
func main() {
|
|
evaluators := []Evaluator{google, yahoo, bing}
|
|
data := "Query"
|
|
r, e := DivideAndConquer(data, evaluators)
|
|
spew.Dump(r, e)
|
|
}
|
|
|
|
var google = func(data interface{}) (interface{}, error) {
|
|
return data, nil
|
|
}
|
|
|
|
var yahoo = func(data interface{}) (interface{}, error) {
|
|
return data, nil
|
|
}
|
|
|
|
var bing = func(data interface{}) (interface{}, error) {
|
|
return data, nil
|
|
}
|
|
|
|
type Evaluator func(data interface{}) (interface{}, error)
|
|
|
|
func DivideAndConquer(data interface{}, evaluators []Evaluator) ([]interface{}, []error) {
|
|
gather := make(chan interface{}, len(evaluators))
|
|
errors := make(chan error, len(evaluators))
|
|
for _, v := range evaluators {
|
|
go func(e Evaluator) {
|
|
result, err := e(data)
|
|
if err != nil {
|
|
errors <- err
|
|
} else {
|
|
gather <- result
|
|
}
|
|
}(v)
|
|
}
|
|
out := make([]interface{}, 0, len(evaluators))
|
|
errs := make([]error, 0, len(evaluators))
|
|
for range evaluators {
|
|
select {
|
|
case r := <-gather:
|
|
out = append(out, r)
|
|
case e := <-errors:
|
|
errs = append(errs, e)
|
|
}
|
|
}
|
|
return out, errs
|
|
}
|