Polyglot CheatSheet - Concurrency

Last Updated: 2023-03-01


  • “Start goroutines when you have concurrent work.”
  • “Share by communicating.”

Don't use asynchronous callbacks.

The Go analogue to a Future is a single-element buffered channel. ch := make(chan Item, 1).

A buffered channel can be used like a semaphore.


A goroutine is a lightweight thread managed by the Go runtime.

go func() {
    // ...

A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.

func main() {
	tick := time.Tick(100 * time.Millisecond)
	boom := time.After(500 * time.Millisecond)
	for {
		select {
		case <-tick:
		case <-boom:
			fmt.Println("    .")
			time.Sleep(50 * time.Millisecond)


Channels are a typed conduit through which you can send and receive values with the channel operator, <-:

// Create a channel (unbuffered, i.e. buffer size = 0).
// Sends and receives block until the other side is ready.
ch := make(chan int)

// Create a buffered channel.
// Sends to a buffered channel block only when the buffer is full.
// Receives block when the buffer is empty.
ch := make(chan int, 100)

// Send v to channel ch.
ch <- v

// Receive from ch, and assign value to v.
v := <-ch

// Senders can close the channel.
// Receiver should never close a channel.
// (Channels do not have to be closed; only when receivers need to be informed.)

// Receivers can test whether a channel has been closed.
v, ok := <-ch

// Receive values from the channel repeatedly until it is closed.
for i := range c

Unbuffered channel allows goroutines to synchronize without explicit locks or condition variables.


In the standard library: sync.Mutex. 2 methods: Lock() and Unlock().

// Create a Mutex
mu sync.Mutex

// Lock

// Do something

// Unlock