Fan-out/fan-in distributes independent work across concurrent goroutines, then gathers the results into one controlled response. Fan-out launches parallel operations; fan-in collects their outputs, combines successful data, and handles errors without waiting for one operation to finish before starting another. section 9.5
A Go implementation typically follows this sequence:
- Create a results channel whose messages contain both successful data and errors. section 9.5.2
- Launch one goroutine per independent task and pass each goroutine its own input. section 9.5.2
- Use a WaitGroup to track completion, then close the results channel after every goroutine finishes. section 9.5.2
- Range over the channel as results arrive, aggregating data and recording errors regardless of completion order. section 9.5.2
Synchronizing multiple news feeds
A /sync HTTP handler fans out by starting a goroutine for each RSS feed URL. Each operation fetches and saves articles with a request timeout, then sends articles and any error through a shared results channel. The handler fans in by collecting all results, returning aggregated articles when successful or a partial-content response containing both articles and errors. section 9.5.2
Listing 9.23 main.go: New handler for fan-out/fan-in call
func (a *App) syncHandler(w http.ResponseWriter, r *http.Request) {
// Fan-out: launch goroutines for each feed
type result struct {
articles []*gofeed.Item
err error
}
resultsChan := make(chan result, len(feeds)) #1
var wg sync.WaitGroup #2
for _, feedURL := range feeds {
wg.Add(1)
go func(url string) {
defer wg.Done()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
fetchedArticles, err := a.fetchFeed(ctx, url)
resultsChan <- result{articles: fetchedArticles, err: err} #3
}(feedURL)
}
// Close results channel after all goroutines complete
go func() {
wg.Wait()
close(resultsChan)
}() #4
Inspect the handler structure for launching goroutines, applying timeouts, publishing results, and coordinating channel closure. section 9.5.2
