logo

Go - Concurrency

Concurrency is part of the language, not a library. 3 key concepts:

  • goroutine: lightweight threads.
  • channels: typed pipes used to communicate and synchronize between goroutines.
  • select: control structure to coordinate concurrent operations.

What is goroutine?

A goroutine is a function or method that executes concurrently alongside any other goroutines using a special goroutine thread. Goroutine threads are more lightweight than standard threads, with most Golang programs using thousands of goroutines at once.

  • to create a goroutine, add the go keyword before the function declaration.

What are Go channels?

Channels are used to transfer data between goroutines.

  • a channel can transfer data of the same type.
  • bidirectional.

Receivers always block until there is data to receive.

If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.

A buffered channel can be used like a semaphore, for instance to limit throughput.

A channel is created by chan.

  • var channel_name chan Type
  • channel_name:= make(chan Type)

To send and received data:

  • send data: channel_name <- element
  • receive data: element := <-Mychannel

read vs write

  • chan // read-write
  • <-chan // read only
  • chan<- // write only

How to stop a gorountine?

To make a goroutine stoppable, let it listen a quit channel.

// Create a quit channel.
quit := make(chan bool)
go func() {
    for {
        select {
        case <-quit:
            return
        default:
            // ...
        }
    }
}()

// Send `true` to quit channel.
quit <- true

How to handle errors from goroutines?

errs := make(chan error, 1)
go func() {
    errs <- foo()
}()

// ...

if err := <-errs; err != nil {
    // handle error
}