Go Channel Patterns - Pooling
Tags: go, programming, tutorial, beginners
Published: 2021-12-13 11:31:39

---
series: [Go Channel Patterns]
---

To improve my Go Programming skills and become a better Go engineer, I have recently purchased an excellent on-demand education from [Ardan Labs](https://www.ardanlabs.com/education/). Materials are created by an expert Go engineer, [Bill Kennedy](https://twitter.com/goinggodotnet).

{% twitter 1464978639355789317 %}


I have decide to record my process of learning how to write more idiomatic code, following Go best practices and design philosophies. 

This series of posts will describe channel patterns used for orchestration/signaling in Go via goroutines.


## Pooling Pattern

The main idea behind **Pooling** pattern is to have:
- a channel that provides a signaling semantics
  - unbuffered channel is used to have a guarantee a goroutine has received a signal
- multiple goroutines that pool that channel for work
- a goroutine that sends work via channel

### Example
In this example you are a `manager`, and you hire a bunch of new `employees`.

`Employees` don't know immediately what do to, and they wait for `manager` to give them some work. The are looking at the channel `ch` to see if there is some work to do.

Once `manager` finds some work for the `employees`, it notifies them by sending a signal (`paper`) via communication channel `ch`.

First available `employee` that sees a signal from the channel `ch`, takes and completes the work. 

After that `employee` completes the work, he is once again available to do more work, and he starts waiting for a new signal on channel `ch`.



Feel free to try the example on [Go Playground](https://play.golang.com/p/pUNW8EcbCvv)

```go
package main

import (
	"fmt"
	"time"
)

func main() {
	// make channel of type string which provides signaling semantics
	// unbuffered channel provides a guarantee that the
	// signal being sent is received
	ch := make(chan string)

	// number of goroutines to create, numCPU() is a good starting point
	//g := runtime.NumCPU()
	g := 3

	for e := 0; e < g; e++ {
		// a new goroutine is created for each employee
		go func(emp int) {
			// employee waits for the signal that there is some work to do
                        // all goroutines are blocked on the same channel `ch` recieve
			for p := range ch {
				fmt.Printf("employee %d : received signal : %s\n", emp, p)
			}

			// when all work is sent, manager notifies all employees by closing the channel
			// once the channel is closed, employee breaks out of the for-range loop
			fmt.Printf("employee %d : revieved shutdown signal\n", emp)
		}(e)
	}

	// amount of work to be done
	const work = 10

	for w := 0; w < work; w++ {
		// when work is ready, we send signal from the manager to the employee
		// sender (manager) has a guarantee that the worker (employee) has received the signal
		// manager doesn't care about which employee received a signal,
		// since all employees are capable of doing the work
		ch <- "paper"

		fmt.Println("manager : sent signal :", w)
	}

	// when all work is sent the manages notifies all employees by closing the channel
	// unbuffered channel provides a guarantee that all work has been sent
	close(ch)
	fmt.Println("manager : sent shutdown signal")

	time.Sleep(time.Second)

}

```

### Result (1st execution)
```sh
go run main.go

employee 2 : recieved signal : paper
manager : sent signal : 0
manager : sent signal : 1
manager : sent signal : 2
manager : sent signal : 3
employee 1 : recieved signal : paper
employee 1 : recieved signal : paper
employee 2 : recieved signal : paper
manager : sent signal : 4
manager : sent signal : 5
manager : sent signal : 6
employee 1 : recieved signal : paper
employee 1 : recieved signal : paper
employee 0 : recieved signal : paper
employee 2 : recieved signal : paper
manager : sent signal : 7
manager : sent signal : 8
manager : sent signal : 9
manager : sent shutdown signal
employee 0 : recieved signal : paper
employee 0 : revieved shutdown signal
employee 2 : revieved shutdown signal
employee 1 : recieved signal : paper
employee 1 : revieved shutdown signal
```

## Conclusion
In this article, pooling channel pattern was described. In addition, simple implementation was provided.

Readers are encouraged to check out excellent [Ardan Labs](https://www.ardanlabs.com/education/) education materials to learn more.

### Note
Depending on the country you are coming from, [Ardan Labs](https://www.ardanlabs.com/education/) education might be a little bit expensive. In that case you can always contact them and they will provide you a link to their scholarship form. 

Resources:
1. [Ardan Labs](https://www.ardanlabs.com/)
2. [Cover image by Igor Mashkov from Pexels](https://www.pexels.com/photo/radio-telescope-against-sky-with-stars-6325001/)