liveBook · Manning

Goroutine

As explained in Learn Concurrent Programming with Go

A goroutine is a lightweight Go execution construct that represents a concurrent activity managed by the Go runtime.

A goroutine is Go’s lightweight unit of concurrent execution. Start one by placing go before a function call; the call runs separately, while the calling goroutine continues to its next instruction. This makes it practical to model many independent activities without directly allocating operating-system threads. section 1.5.1 section 2.3.1 section 2.3

Run independent work concurrently

A loop that calls doWork(i) normally completes one one-second task before starting the next, taking about five seconds for five tasks. Changing the call to go doWork(i) starts all five activities without waiting at each call, so their start and finish messages can appear in a different order and complete around the same time. The order is observable but not guaranteed by the creation loop. section 2.3.1

Listing 2.3 Main thread calling the doWork() function in parallel
func main() {
    for i := 0; i < 5; i++ {
        go doWork(i)              #1
    }
    time.Sleep(2 * time.Second)   #2
}
#1 Starts a new goroutine that calls the doWork() function
#2 Waits for all of the work to finish using a longer sleep

Compare the sequential call with the go-prefixed call. The sleep keeps main alive long enough for the child goroutines to finish, but it is only a temporary waiting technique. section 2.3.1

A goroutine is neither a process nor an operating-system thread. Current Go implementations group goroutine executions onto operating-system threads, with the runtime handling scheduling and context switching at the application level. The language specification does not strictly require one implementation strategy. section 2.3.2 section 2.3

Creating concurrent work does not by itself make a program correct. When main() runs out of instructions, it terminates the process, possibly before child goroutines run or finish. Concurrent goroutines may also share memory: one can update a countdown variable while another reads it, or many can update a shared letter-frequency slice. Such shared updates need careful coordination to avoid incorrect results and race conditions. section 2.3.1 section 3.2.1 section 3.2.3

Choose how goroutines cooperate based on the work and its data flow:

  • Use channels when isolated goroutines should exchange messages or synchronize; this CSP-style approach reduces the risk of race conditions. section 1.5.2
  • Use shared memory with classical primitives when that model better fits the problem or gives better performance. section 1.5.2
  • Send a function result on a channel when background work must later return a value; receiving blocks until that result is available. section 7.1.5

Collect a background result

An anonymous goroutine can compute the factors of one large number and send its slice result on resultCh while main() computes factors for another. Reading <-resultCh retrieves the background result, waiting if necessary. This replaces an unsafe or awkward attempt to guess completion timing with a defined handoff point. section 7.1.5

Figure 1.5 A concurrent Go application using CSP

The diagram shows the CSP arrangement: isolated concurrent executions coordinate by sending messages through channels rather than directly sharing state. section 1.5.2

Goroutines help applications stay responsive, improve throughput during I/O waits, and can provide speedup on multiple processors. They do not remove limits imposed by serial work: performance still depends on the problem, available hardware, coordination costs, and the non-parallel portion of execution. section 1.7 section 1.0

How Learn Concurrent Programming with Go covers it

How deep it goes
Defines creation and runtime placement, then demonstrates execution order, shared memory, and channel-based result collection without prescribing a required implementation.
Examples
Uses sleeping work calls, a shared countdown, concurrent web-page letter counting, file-search exercises, and parallel factor calculations.
What it assumes
Introduces goroutines after distinguishing processes, threads, concurrency, and parallelism, without requiring operating-system internals.
What you can do after
Apply it via Go’s go keyword to run functions concurrently and use channels to collect background results.
How it connects
Connects goroutines with channels, CSP, shared memory, mutexes, condition variables, processes, threads, race conditions, and parallelism.

Also explained in

Compare how 7 books explain goroutine →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Concurrent Programming with Go. The section links point to the parts of the book it draws on.