Closed3

Go Concurrency Patterns

shusannshusann

Summary
In just a few simple transformations we used Go's concurrency primitives to convert a

slow

  • sequential
  • failure-sensitive
  • program into one that is

fast

  • concurrent
  • replicated
  • robust.
shusannshusann

p.50: Google Search 3.0 complete program

var (
	Web1   = fakeSearch("web")
	Web2   = fakeSearch("web")
	Image1 = fakeSearch("image")
	Image2 = fakeSearch("image")
	Video1 = fakeSearch("video")
	Video2 = fakeSearch("video")
)

// This generate Search type function based on searchType
func fakeSearch(searchType string) Search {
	return func(query string) Result { return Result{} }
}

// Function type contruct
type Search func(query string) Result

// Anything should be fine
type Result struct{}

// Run search concurrently on multiple replicas
// the fastest one is used, and others are discarded
func First(query string, replicas ...Search) Result {
	c := make(chan Result)
	searchReplica := func(i int) { c <- replicas[i](query) }
	for i := range replicas {
		go searchReplica(i)
	}
	return <-c
}

// Assuming in part of layered arch
type SearchUseCase struct {
	results []Result
}

// The main logic performs operation
func (su *SearchUseCase) Query(query string) {
	c := make(chan Result)
	timeout := time.After(3 * time.Second)

	go func() { c <- First(query, Web1, Web2) }()
	go func() { c <- First(query, Image1, Image2) }()
	go func() { c <- First(query, Video1, Video2) }()
	for i := 0; i < 3; i++ {
		select {
		case result := <-c:
			su.results = append(su.results, result)
		case <-timeout:
			fmt.Println("timeout")
			return
		}
	}
}
このスクラップは2023/11/15にクローズされました