I recently revisited a project I had worked on some time ago, where the system was required to take multiple parameters, query data from various sources, and then return a unified response. Reflecting on that project, I became curious about how I would approach building this process today. As a result, I decided to create a simple template to run multiple strategies concurrently.
A Simple Version
In this example, we’ll explore how to run multiple strategies in parallel using goroutines and channels. We’ll build a simple system that processes multiple strategies concurrently and returns a unified response from all of them.
package main
import (
"context"
"fmt"
"sync"
)
func main() {
// Create a context with a timeout
ctx := context.Background()
// Create a WaitGroup to synchronize goroutines
var wg sync.WaitGroup
// List of strategy names
strategies := []Strategy{
&strA{},
&strB{},
}
// start a response channel
responseCh := make(chan []byte, len(strategies))
// Launch each strategy in a separate goroutine
for _, str := range strategies {
wg.Add(1)
go func(ctx context.Context, s Strategy) {
defer wg.Done()
resp, err := s.Process(ctx)
if err != nil {
fmt.Println("Error processing strategy:", err)
return
}
responseCh $lt;- resp
}(ctx, str)
}
// Wait for all goroutines to finish
wg.Wait()
// Close the response channel
close(responseCh)
out := make([]byte, 0, len(strategies))
for resp := range responseCh {
out = append(out, resp...)
}
// Print the responses
fmt.Println("All strategies finished")
fmt.Println("Responses:", string(out))
}
// Strategy is an interface that contains the methods to process strategies
type Strategy interface {
// Process processes the strategy
Process(ctx context.Context) ([]byte, error)
}
// strA is a struct that contains the methods to process a dummy strategy
type strA struct{}
// Implements the strategy interface
func (s *strA) Process(ctx context.Context) ([]byte, error) {
return []byte("A"), nil
}
// strB is a struct that contains the methods to process a dummy strategy
type strB struct{}
// Implements the strategy interface
func (s *strB) Process(ctx context.Context) ([]byte, error) {
return []byte("B"), nil
}
Strategy Interface
I define a Strategy interface that outlines a Process method. Each strategy struct (in this case, strA and strB) implements this interface, allowing us to process them in a uniform way.
For simplicity, we define two strategies (strA and strB) that simulate some work and return dummy data.
Conclusion
This example demonstrates how to run multiple strategies in parallel using goroutines and channels in Go. By using sync.WaitGroup to ensure all goroutines complete, and channels to collect the results, we can efficiently run concurrent processes and gather their output into a unified response. This approach can easily be extended to more complex strategies or integrated into larger systems.
Comments
Post a Comment