ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Fan-Out Pattern for Parallel Task Execution

Go

Goal -- WPM

Ready
Exercise Algorithm Area
1package main
2
3import (
4 "fmt"
5 "sync"
6 "time"
7)
8
9// Task represents a unit of work.
10type Task struct {
11 ID int
12 Name string
13}
14
15// Result represents the outcome of a task.
16type Result struct {
17 TaskID int
18 Output string
19 Err error
20}
21
22// worker executes a task and returns a result.
23func worker(id int, tasks <-chan Task, results chan<- Result, wg *sync.WaitGroup) {
24 defer wg.Done()
25 for task := range tasks {
26 fmt.Printf("Worker %d starting task %d\n", id, task.ID)
27 // Simulate work
28 t time.Sleep(time.Millisecond * 100)
29 var output string
30 if task.ID%2 == 0 {
31 output = fmt.Sprintf("Task %d (%s) completed successfully.", task.ID, task.Name)
32 } else {
33 // Simulate an error for odd-numbered tasks
34 results <- Result{TaskID: task.ID, Err: fmt.Errorf("task %d failed", task.ID)}
35 continue // Skip successful output for failed tasks
36 }
37 results <- Result{TaskID: task.ID, Output: output}
38 }
39}
40
41func main() {
42 numTasks := 10
43 numWorkers := 3
44
45 tasks := make(chan Task, numTasks)
46 results := make(chan Result, numTasks)
47
48 var wg sync.WaitGroup
49
50 // Start workers.
51 wg.Add(numWorkers)
52 for i := 0; i < numWorkers; i++ {
53 go worker(i, tasks, results, &wg)
54 }
55
56 // Submit tasks.
57 for i := 0; i < numTasks; i++ {
58 tasks <- Task{ID: i, Name: fmt.Sprintf("Task-%d", i)}
59 }
60 close(tasks)
61
62 // Wait for all workers to finish processing tasks.
63 wg.Wait()
64 close(results)
65
66 // Collect and print results.
67 fmt.Println("\n--- Results ---")
68 var successfulResults []string
69 var failedTasks []int
70
71 for res := range results {
72 if res.Err != nil {
73 fmt.Printf("Task %d failed: %v\n", res.TaskID, res.Err)
74 failedTasks = append(failedTasks, res.TaskID)
75 } else {
76 fmt.Printf("Task %d succeeded: %s\n", res.TaskID, res.Output)
77 successfulResults = append(successfulResults, res.Output)
78 }
79 }
80
81 fmt.Printf("\nTotal tasks: %d, Successful: %d, Failed: %d\n", numTasks, len(successfulResults), len(failedTasks))
82}
Algorithm description viewbox

Fan-Out Pattern for Parallel Task Execution

Algorithm description:

This Go program implements the fan-out pattern for parallel task execution. It creates a pool of worker goroutines, each capable of processing tasks. Tasks are sent to a shared task channel, and workers concurrently pick up tasks, process them, and send their results (or errors) to a results channel. The main goroutine then collects all results. This pattern is ideal for distributing independent work across multiple processors to achieve faster completion times.

Algorithm explanation:

The program defines `Task` and `Result` structs to represent work items and their outcomes. The `worker` function runs as a goroutine, continuously reading `Task`s from the `tasks` channel. For each task, it simulates work, potentially returning an error or a successful output. The `wg.Done()` call ensures that the WaitGroup is decremented when a worker finishes processing all tasks from the channel. The `main` function initializes task and result channels, and a `sync.WaitGroup`. It launches a fixed number of `worker` goroutines. Then, it populates the `tasks` channel with all the work items and closes it to signal that no more tasks will be added. After closing the `tasks` channel, it waits for all workers to complete using `wg.Wait()`. Finally, it closes the `results` channel and iterates through it to collect and display all successful outputs and encountered errors. This pattern effectively parallelizes work and centralizes the reporting of outcomes.

Pseudocode:

1. Define Task and Result structs.
2. Implement a worker function that takes task channel, result channel, and WaitGroup.
3. Inside worker: loop through tasks channel, simulate work, send Result to results channel, defer WaitGroup decrement.
4. In main: create task and result channels, WaitGroup.
5. Launch numWorkers goroutines, passing channels and WaitGroup.
6. Populate task channel with tasks.
7. Close task channel.
8. Wait for WaitGroup to finish.
9. Close result channel.
10. Iterate through result channel, process successful and failed results.