This post is the follow up to Review: Concurrency in Go: Chapters 1-3.
This chapter is the meat of the book. Cox-Buday devotes sixty pages to covering concurrency patterns–almost a third of the book’s total pages.
The chapter starts with a discussion of confinement: “the simple yet powerful idea of ensuring information is only ever available from one concurrent process.” She identifies two types of confinement: lexical and ad-hoc. Ad-hoc confinement “is when you achieve confinement through a convention.” Lexical confinment “involves using lexical scope to expose only the correct data and concurrency primitives for multiple concurrent processes to use.” As she does in the early chapters of the book, Cox-Buday provides concrete examples of each.
From here, the remainder of the chapter dives in to the concurrency patterns themselves.
- For-select loop
- Pipelines, Fan-in, Fan-out
- Or-done channel
- Tee channel
- Bridge channel
The penultimate chapter focuses on concurrency at scale. The chapter begins with a discussion of error handling in the context of concurrency. It’s an extention of the Error Handling section from Chapter 4, and focuses on the what rather than the how of error handling. Cox-Buday identifies four critical pieces of information that errors should contain:
- What happened
- When and where it occurred
- User-friendly message
- How the user can get more info
Ultimately, she ends up talking about wrapped errors and progapation through a complex system. Since the book’s
publication in 2017, and the release of 1.13, the Go team has introduced the convention of the
Unwrap method, which returns the
underlying error. Go 1.13 also introduced two new functions in the
As. The former
compares an error to a value; the latter tests the error’s type. For more details about these changes, read the
Working with Errors in Go 1.13 blog post.
Next, Cox-Buday tackles the subject of timeouts and cancellations. She starts by outlining the reasons one might want to use timeouts:
- System saturation
- Stale data
- Attempting to prevent deadlocks
From here, she turns to the reasons for cancellations, including:
- User intervention
- Parent cancellation
- Replicated requests
Then she walks through a concrete example that explores the hows and whys of timeouts and cancellations.
Heartbeats is the next topic tackled in this chapter and focuses on two types of heartbeats:
- Heartbeats that occur on a time interval
- Heartbeats that occur at the beginning of a unit of work
The remainder of the chapter continues along this pattern to cover the topics of replicated requests, rate limiting, and healing unhealthy goroutines.
In the book’s final chapter, Cox-Buday dives into the Go runtime and its management of goroutines. She starts by talking about the work stealing strategy the runtime uses to multiplex goroutines onto OS threads. She defines the work stealing algorithm, then walks the reader through a function that computes the Fibonacci sequence recursively and how it is treated by the algorithm.
Although the chapter is technically dense, I never felt like it was indecipherable. I didn’t read this chapter all at once, but rather over the course of several days, because I would read a little bit and then have to sit with it for it to make sense.
For such a slim book, it holds a wealth of detailed information about Go’s concurrency model. From laying out the foundations of Go’s concurrency primitives, to the outlining of concurrency patterns, to the scaling of goroutines, Cox-Buday does a remarkable job of writing a deeply technical book that is also readable. At first, I thought the $43 USD price tag (on Amazon) was steep. After reading it, I think it’s $43 well spent.