Menu
Coddy logo textTech

Recap - Worker Pool

Part of the Object Oriented Programming section of Coddy's GO journey — lesson 66 of 107.

challenge icon

Challenge

Easy

Let's build a task processing system using the worker pool pattern! You'll create a pool of workers that concurrently process computational tasks, demonstrating how channels, goroutines, and WaitGroups work together to handle workloads efficiently.

You'll organize your code across two files:

  • pool.go: Define your worker pool components and logic.

    Create a Task struct with ID (int) and Value (int) fields representing work to be done.

    Create a Result struct with TaskID (int) and Computed (int) fields representing completed work.

    Implement a Worker function that takes a worker ID (int), a receive-only channel of tasks (<-chan Task), a send-only channel for results (chan<- Result), and a pointer to a sync.WaitGroup. Each worker should:

    • Use defer wg.Done() to signal completion
    • Range over the tasks channel to process each task
    • For each task, compute the square of the task's Value
    • Send a Result with the TaskID and the computed square

    Implement a RunPool function that takes the number of workers (int) and a slice of tasks. This function should:

    • Create buffered channels for tasks and results (use the number of tasks as the buffer size)
    • Start the specified number of workers as goroutines
    • Send all tasks to the tasks channel, then close it
    • Use a goroutine with the WaitGroup to close the results channel after all workers finish
    • Collect all results into a slice and return it

  • main.go: Read input and coordinate the worker pool.

    Read the number of workers, then the number of tasks. For each task, read its ID and value. Call RunPool with the workers and tasks, then print each result in the format: Task [TaskID]: [Computed]

    Print results sorted by TaskID in ascending order.

The following inputs will be provided:

  • Line 1: Number of workers (integer)
  • Line 2: Number of tasks (integer)
  • Following lines: For each task, two lines - the task ID (integer), then its value (integer)

For example, given:

2
4
1
3
2
5
3
2
4
7

Your output should be:

Task 1: 9
Task 2: 25
Task 3: 4
Task 4: 49

The workers process tasks concurrently (3 squared is 9, 5 squared is 25, etc.), and the results are collected and displayed in order by task ID. With 2 workers handling 4 tasks, the work is distributed across the pool efficiently.

Try it yourself

package main

import (
	"fmt"
	"sort"
)

func main() {
	// Read number of workers
	var numWorkers int
	fmt.Scanln(&numWorkers)

	// Read number of tasks
	var numTasks int
	fmt.Scanln(&numTasks)

	// Read tasks
	tasks := make([]Task, numTasks)
	for i := 0; i < numTasks; i++ {
		var id, value int
		fmt.Scanln(&id)
		fmt.Scanln(&value)
		tasks[i] = Task{ID: id, Value: value}
	}

	// TODO: Call RunPool with workers and tasks

	// TODO: Sort results by TaskID in ascending order

	// TODO: Print each result in the format: Task [TaskID]: [Computed]
}

All lessons in Object Oriented Programming