Concurrency · 3 MIN READ

The worker pool, written once

Build a fixed set of workers that finishes cleanly.

A fixed number of workers bounds concurrent processing. The producer sends jobs and closes the input stream after the last job. Workers consume it until it is drained. A coordinator waits for every worker before closing the output stream.

Results may need to be consumed while jobs are still being produced, or backpressure can deadlock the producer and workers. Add cancellation deliberately, and test termination as well as returned values.

SEE THE IDEA

Bound the workers while letting jobs flow

  1. 01

    Jobs channel

    go
    jobs <- job

    One producer feeds the queue

  2. 02

    Worker A

    go
    for job := range jobs

    Processes a job at a time

  3. 03

    Worker B

    go
    for job := range jobs

    Shares the same bounded workload

A fixed worker count bounds concurrent processing, not the total number of jobs.

In practice

Coordinate the full lifecycle: start workers, deliver jobs, close the jobs stream, wait for workers, then close the results stream. A separate results consumer may need to run while jobs are produced so backpressure cannot deadlock the producer.

Watch out

Do not close results from an individual worker. Another worker may still be sending.

Official reference ↗

Work through the exercise

go
package main

// Squares runs the numbers through workers goroutines and returns
// every square. Order does not matter; finishing does.
func Squares(numbers []int, workers int) []int {
	return nil
}

func main() {}
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.