liveBook · Manning

Goroutine

As explained in Go in Action, Second Edition

A lightweight Go execution unit that runs a function concurrently with the rest of a program.

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

How Go in Action, Second Edition covers it

How deep it goes
Explains launch syntax and runtime scheduling, then develops completion, cancellation, and fan-out/fan-in coordination through an HTTP handler.
Examples
Uses RSS feed fetching, premature program exit, and an HTTP endpoint that aggregates articles and errors from concurrent fetches.
What it assumes
Assumes familiarity with Go functions and application code, while introducing the `go` launch syntax without requiring thread-pool setup.
What you can do after
Build it from scratch: launch and coordinate concurrent feed fetches, collect their results, and avoid abandoning unfinished work.
How it connects
Connects goroutines to channels, context, WaitGroup, worker pools, mutexes, and race detection.

Also explained in

Compare how 7 books explain goroutine →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Action, Second Edition. The section links point to the parts of the book it draws on.