mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2025-02-21 07:53:13 +03:00
another package of fetchers
This commit is contained in:
parent
54a3ffe76b
commit
dc000eb40f
@ -9,6 +9,14 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"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 RunDivideAndConquer() {
|
func RunDivideAndConquer() {
|
||||||
type in struct {
|
type in struct {
|
||||||
a int
|
a int
|
||||||
|
@ -1 +1,92 @@
|
|||||||
package fetchers
|
package fetchers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fetcher interface {
|
||||||
|
Fetch(url string) (string, error)
|
||||||
|
GetName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoogleFetcher struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GoogleFetcher) Fetch(url string) (string, error) {
|
||||||
|
return fmt.Sprintf("%s is fetching %s", g.Name, url), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GoogleFetcher) GetName() string {
|
||||||
|
return g.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGoogleFetcher(name string) *GoogleFetcher {
|
||||||
|
return &GoogleFetcher{Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BingFetcher struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BingFetcher) Fetch(url string) (string, error) {
|
||||||
|
return fmt.Sprintf("%s is fetching %s", b.Name, url), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BingFetcher) GetName() string {
|
||||||
|
return b.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBingFetcher(name string) *BingFetcher {
|
||||||
|
return &BingFetcher{Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DuckDuckGoFetcher struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DuckDuckGoFetcher) Fetch(url string) (string, error) {
|
||||||
|
return fmt.Sprintf("%s is fetching %s", d.Name, url), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DuckDuckGoFetcher) GetName() string {
|
||||||
|
return d.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDuckDuckGoFetcherFetcher(name string) *DuckDuckGoFetcher {
|
||||||
|
return &DuckDuckGoFetcher{Name: name}
|
||||||
|
}
|
||||||
|
func FetchResults(url string, fetchers []Fetcher, timeout time.Duration) ([]string, []error) {
|
||||||
|
chStr := make(chan string)
|
||||||
|
chErr := make(chan error)
|
||||||
|
for _, f := range fetchers {
|
||||||
|
go func(f Fetcher) {
|
||||||
|
s, err := f.Fetch(url)
|
||||||
|
if err != nil {
|
||||||
|
chErr <- err
|
||||||
|
} else {
|
||||||
|
chStr <- s
|
||||||
|
}
|
||||||
|
}(f)
|
||||||
|
}
|
||||||
|
stringResults := []string{}
|
||||||
|
errorResults := []error{}
|
||||||
|
for range fetchers {
|
||||||
|
select {
|
||||||
|
case s := <-chStr:
|
||||||
|
stringResults = append(stringResults, s)
|
||||||
|
case e := <-chErr:
|
||||||
|
errorResults = append(errorResults, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringResults, errorResults
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunFetchers() {
|
||||||
|
fetchers := []Fetcher{NewGoogleFetcher("Google"), NewGoogleFetcher("Bing"), NewGoogleFetcher("Duck Duck Go")}
|
||||||
|
r, e := FetchResults("http://www.abc.com", fetchers, time.Millisecond*100)
|
||||||
|
spew.Dump(r, e)
|
||||||
|
}
|
||||||
|
@ -1,15 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/jianhan/go-patterns/concurrency/subtasks/divide_and_conquer"
|
import "github.com/jianhan/go-patterns/concurrency/subtasks/fetchers"
|
||||||
|
|
||||||
// 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() {
|
func main() {
|
||||||
divide_and_conquer.RunDivideAndConquer()
|
// divide_and_conquer.RunDivideAndConquer()
|
||||||
|
fetchers.RunFetchers()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user