Golang Worker Pattern Example

An example of the worker pattern in Go. Executes, e.g., 20 units of work with 20 workers, taking 2 seconds each, in 2 seconds. ```go package main // // $ go build worker.go && WORKERS=20 JOBS=20 ./worker // import ( "fmt" "os" "strconv" "sync" "time" ) // A unit of work type Rabbit struct { ID int Name string } // The worker accepting a unit of work type RabbitWork struct { Rabbit Rabbit } func main() { jobCount, _ := strconv.Atoi(os.Getenv("JOBS")) workerCount, _ := strconv.Atoi(os.Getenv("WORKERS")) start := time.Now() workers := make(chan RabbitWork, workers) var wg sync.WaitGroup // Add workers to our startup "Icarus" for i := 0; i < workerCount; i++ { wg.Add(1) go func() { for work := range workers { // do some work on data var rabbit = work.Rabbit fmt.Println("Capturing", rabbit.Name, "(", rabbit.ID, ")") time.Sleep(2 * time.Second) fmt.Println("Skinned", rabbit.Name, "(", rabbit.ID, ")") } wg.Done() }() } // Give some work to the workers for i := 1; i <= jobCount; i++ { workers <- RabbitWork{ Rabbit: Rabbit{Name: "Toffe", ID: i}, } } // Wait for workers to do their job close(workers) wg.Wait() fmt.Println("Work took", time.Since(start).Seconds(), "seconds") } ``` Notes ----- 1. WaitGroup waits for all work to finish 2. wg.Wait() blocks until wg.Done() is called 20 times 3. workers <- RabbitWork will block if all 20 workers are busy working 4. for data := range tasks iterates over incoming work sent through the tasks channel 5. close(workers) closes the channel 6. 40 units of work with 20 workers will complete in 4 seconds 7. also see: