github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2014/gotham-context/first-context.go (about) 1 // +build OMIT 2 3 package main 4 5 import ( 6 "fmt" 7 "math/rand" 8 "time" 9 10 "golang.org/x/net/context" 11 ) 12 13 type Result struct { 14 Hit string 15 Err error 16 } 17 18 // START1 OMIT 19 // Search runs query on a backend and returns the result. 20 type Search func(ctx context.Context, query string) Result // HL 21 22 // First runs query on replicas and returns the first result. 23 func First(ctx context.Context, query string, replicas ...Search) Result { 24 c := make(chan Result, len(replicas)) 25 ctx, cancel := context.WithCancel(ctx) // HL 26 defer cancel() // HL 27 search := func(replica Search) { c <- replica(ctx, query) } // HL 28 for _, replica := range replicas { 29 go search(replica) 30 } 31 select { 32 case <-ctx.Done(): // HL 33 return Result{Err: ctx.Err()} // HL 34 case r := <-c: 35 return r 36 } 37 } 38 39 // STOP1 OMIT 40 41 // START2 OMIT 42 func main() { 43 rand.Seed(time.Now().UnixNano()) 44 start := time.Now() 45 result := First(context.Background(), 46 "golang", 47 fakeSearch("replica 1"), 48 fakeSearch("replica 2")) 49 elapsed := time.Since(start) 50 fmt.Printf("%+v\n", result) 51 fmt.Println(elapsed) 52 } 53 54 // STOP2 OMIT 55 56 func fakeSearch(kind string) Search { 57 return func(ctx context.Context, query string) Result { 58 time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) 59 return Result{Hit: fmt.Sprintf("%s result for %q\n", kind, query)} 60 } 61 }