I must be having a brain block here, but I am getting blocked when iterating over a buffered channel
results := []search.Book{}
resultsStream := make(chan []search.Book, 2)
defer close(resultsStream)
// parallelize searches to optimize response time
for _, src := range sources {
go src.Search(bookName, resultsStream)
}
counter := 0
for sourceResults := range resultsStream {
counter = counter 1
results = append(results, sourceResults...)
fmt.Println(counter)
}
fmt.Println("Never called")
Output
1
2
This proves the 2 sources populate the channel (which is the max capacity).
What am I missing here? Never called
is, well, never called.
Edit
var wg sync.WaitGroup
results := []search.Book{}
resultsStream := make(chan []search.Book, len(sources))
defer close(resultsStream)
// parallelize searches to optimize response time
for _, src := range sources {
wg.Add(1)
go src.Search(bookName, resultsStream, &wg)
}
wg.Wait()
close(resultsStream)
for sourceResults := range resultsStream {
results = append(results, sourceResults...)
}
c.JSON(http.StatusOK, gin.H{
"results": results,
})
CodePudding user response:
The loop for sourceResults := range resultsStream
receives values from the channel repeatedly until it is closed. Once sender is done and closes the channel loop will end.
You can create new channel for each parallel search and once all worker goroutines finish you can close that channel. That will end the receiver loop (NOTE: don't close channel from the receiver side as senders won't know and sending to a closed channel causes panic).
CodePudding user response:
When you range
over a go channel the for loop is not exited until you either break
out of it or the channel is closed using close(resultsStream)