Skip to content

Instantly share code, notes, and snippets.

@kcollasarundell
Created August 14, 2019 06:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kcollasarundell/0d7b5bf48431e97e79c0ab3cce13f955 to your computer and use it in GitHub Desktop.
Save kcollasarundell/0d7b5bf48431e97e79c0ab3cce13f955 to your computer and use it in GitHub Desktop.
func aggregate(baseCtx context.Context) {
ctx, cancel := context.WithTimeout(baseCtx, 5*time.Second)
defer cancel()
ch := make(chan *http.Response)
var wg *sync.WaitGroup
var sources []string
for _, src := range sources {
wg.Add(1)
go func(ctx context.Context, source string) {
defer wg.Done()
resp, err := makeRequest(ctx, source)
if err != nil {
// log error
}
ch <- resp
}(ctx, src)
}
go func(wg *sync.WaitGroup) {
wg.Wait()
close(ch)
}(wg)
results := make([]*http.Response, 0, len(sources))
for {
select {
case resp := <-ch:
results = append(results, resp)
case <-ctx.Done():
break
}
}
// use results
}
@spy16
Copy link

spy16 commented Aug 14, 2019

i see 2 issues here:

  1. results := make([]*http.Response, 0, len(sources)) and the for is appending into this, which means len(sources) number of elements in this slice will be nil pointers forever and actual response will be added after that.
  2. consider that all goroutines finish and write response to ch. the for loop is collecting it and adding it to the results. But problem is, it will keep on doing this (even after close(ch) since reading from a closed channel returns zero-value) until ctx.Done() returns ..
func aggregate(baseCtx context.Context) {
	ctx, cancel := context.WithTimeout(baseCtx, 5*time.Second)
	defer cancel()
	ch := make(chan *http.Response)
	var wg *sync.WaitGroup
	var sources []string
	for _, src := range sources {
		wg.Add(1)
		go func(ctx context.Context, source string) {
			defer wg.Done()
			resp, err := makeRequest(ctx, source)
			if err != nil {
				// log error
			}
			ch <- resp

		}(ctx, src)
	}
	go func(wg *sync.WaitGroup) {
		wg.Wait()
		close(ch)
	}(wg)
	var results []*http.Response
	for {
		select {
		case resp, ok := <-ch:
                        if !ok {
                              break
                        }
			results = append(results, resp)
		case <-ctx.Done():
			break
		}
	}

	// use results
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment