Goroutines and channels are powerful language structs that make golang a powerful concurrent language. In the first part of the article, we explored, how we can build a workerpool to optimize the performance of the concurrency structs of golang namely limiting the resource utilization. But it was a simple example to demonstrate how we can go about it.

Here, we will build a robust solution according to the learning from the first part so that we can use this solution in any application. There are some solutions on the internet with complex architecture using dispatchers and all. In reality, we do not need it, we can do everything using one shared channel. Let’s see how we can build that here

Architecture

Here we make a generic workerpool package that can handle tasks with workers based on the desired concurrency. Let’s see the directory structure.

workerpool
├── pool.go
├── task.go
└── worker.go

The

workerpool directory is in the root folder of the project. Let’s go over what Task is. Task is a single unit of work that needs to be processed. Worker is a simple worker function that handles running the task. And Pool actually handles the creation and managing the workers.

Implementation

Let’s code out

Task first.

// workerpool/task.go

package workerpool

import (
	"fmt"
)

type Task struct {
	Err  error
	Data interface{}
	f    func(interface{}) error
}

func NewTask(f func(interface{}) error, data interface{}) *Task {
	return &Task{f: f, Data: data}
}

func process(workerID int, task *Task) {
	fmt.Printf("Worker %d processes task %v\n", workerID, task.Data)
	task.Err = task.f(task.Data)
}

#golang #programming #backend #optimization

Concurrency in Golang And WorkerPool [Part 2]
2.15 GEEK