This chapter covers
- Preventing common mistakes regarding the main Go concurrency primitives: goroutines and channels
- Understanding the impacts of using the standard data structures alongside concurrent code
- Delving into the standard library and some extensions
- Discussing subtle bugs that may lead to data races or even deadlock situations
In the previous chapter, we discussed the foundations regarding concurrency. Now, it’s time to delve into practice and concrete mistakes made by Go developers when working with the concurrency primitives.
Contexts are omnipresent when working with concurrency in Go, and in many situations, it may be recommended to propagate them. However, sometimes context propagation can lead to subtle bugs, preventing subfunctions from being correctly executed.
Let’s consider the following example. We expose an HTTP handler that performs some tasks and returns a response. However, just before returning the response, we want also to send it to a Kafka topic. As we don’t want to penalize the HTTP consumer latency-wise, we want the publish action to be handled asynchronously within a new goroutine. We assume that we have at our disposal a publish function, accepting a context so that the action of publishing a message can be interrupted if the context is canceled, for example.
Here would be a possible implementation: