Created
June 20, 2020 08:12
-
-
Save bobby569/eb145d8e04c8e8701f5795eabe9f4f8b to your computer and use it in GitHub Desktop.
Taking how google search works to demonstrate the concurrency idea of golang.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "fmt" | |
| "math/rand" | |
| "time" | |
| ) | |
| var ( | |
| // Web is the web search engine | |
| Web = fakeSearch("web") | |
| // Image is the image search engine | |
| Image = fakeSearch("image") | |
| // Video is the video search engine | |
| Video = fakeSearch("video") | |
| ) | |
| // Result is the results from the google search | |
| type Result string | |
| // Search is the action of the google search | |
| type Search func(query string) Result | |
| func fakeSearch(kind string) Search { | |
| return func(query string) Result { | |
| time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) | |
| return Result(fmt.Sprintf("%s result for %q\n", kind, query)) | |
| } | |
| } | |
| // Google (serial) function takes a query and returns a slice of Results. | |
| func Google(query string) (results []Result) { | |
| results = append(results, Web(query)) | |
| results = append(results, Image(query)) | |
| results = append(results, Video(query)) | |
| return | |
| } | |
| // Google (parallel) function takes a query and returns a slice of Results. | |
| func Google(query string) (results []Result) { | |
| c := make(chan Result, len(3)) | |
| go func() { c <- First(query, Web1, Web2) }() | |
| go func() { c <- First(query, Image1, Image2) }() | |
| go func() { c <- First(query, Video1, Video2) }() | |
| timeout := time.After(80 * time.Millisecond) | |
| for i := 0; i < 3; i++ { | |
| select { | |
| case result := <-c: | |
| results = append(results, result) | |
| case <-timeout: | |
| fmt.Println("timeout") | |
| return | |
| } | |
| } | |
| return | |
| } | |
| // First send requests to multiple replicas and use the first response | |
| // to avoid discarding resutls from slow servers. | |
| func First(query string, replicas ...Search) Result { | |
| c := make(chan Result, len(replicas)) | |
| searchReplica := func(i int) { c <- replicas[i](query) } | |
| for i := range replicas { | |
| go searchReplica(i) | |
| } | |
| return <-c | |
| } | |
| func main() { | |
| start := time.Now() | |
| results := First("golang", | |
| fakeSearch("replica 1"), | |
| fakeSearch("replica 2")) | |
| elapsed := time.Since(start) | |
| fmt.Println(results) | |
| fmt.Println(elapsed) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment