A goroutine runs a Go function concurrently with the rest of the program. Start one by putting `go` before a function call, as in `go printFeedTitle(url)`. The Go runtime schedules goroutines across OS threads; you do not configure a thread pool. A goroutine starts with only a few kilobytes of stack, making many concurrent operations practical. section 1.4.1 section 9.1
Fetching feeds without blocking the caller
An RSS reader can launch a goroutine for each feed URL instead of waiting for one network fetch before starting the next. Launching them is not enough, though: if `main` returns, the program exits and unfinished goroutines stop. A fixed `time.Sleep` only guesses when the work will finish; use explicit coordination instead. section 9.1 section 9.5.2
For work that must finish or stop cleanly:
- Pass results through channels, and use a `sync.WaitGroup` or `errgroup` to track completion. Protect any shared data with a mutex. section 9.5.2 section 9.6.1
- Use `context.Context` for cancellation or deadlines so work can stop when it is no longer needed. section 1.4.2 section 9.6.1
- Limit the number of goroutines when the workload could exceed available resources, and check concurrent code with `go test -race`. section 9.6.1
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
The feed-sync handler shows fan-out in practice: one goroutine per URL sends a result, while a WaitGroup lets another goroutine close the results channel after every fetch completes. section 9.5.2
Use goroutines where tasks can make independent progress, especially across network requests or other I/O. They provide concurrency, not a guarantee that tasks execute simultaneously. Keep strictly ordered or single-task code sequential when concurrency adds no benefit. section 9.0 section 9.7






