Skip to content

Instantly share code, notes, and snippets.

@cassava
Created July 1, 2013 07:17
Show Gist options
  • Save cassava/5898929 to your computer and use it in GitHub Desktop.
Save cassava/5898929 to your computer and use it in GitHub Desktop.
An idiom in Go for managing up to a fixed number of workers and separately post-processing the results.
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
// worker does work which takes a (variable) amount of time.
// Here it is simulated by waiting a random amount of time.
func worker(s string, ch chan<- string) {
time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
ch <- s
}
// manager spawns at most routines amount of workers and connects all the
// different entities and functions together.
//
// manager panics if routines <= 0.
func manager(texts []string, routines int) {
var (
ch = make(chan string) // for communication between worker and receiver
active = make(chan bool, routines-1) // for coordination of multiple workers
alive = make(chan struct{}) // blocking as long as receiver is alive
)
// Start the receiver and start creating workers as quickly as possible.
go receiver(ch, active, alive)
for _, s := range texts {
active <- true
go worker(s, ch)
}
// Signal that we have finished creating workers, then wait for receiver to finish.
active <- false
<-alive
}
// receiver evaluates the worker's results one after another.
//
// For each worker sent into existence, a true value must be queued onto active.
// When the last worker has embarked, false should be queued, which causes
// receiver to finalize and finish.
func receiver(ch <-chan string, active <-chan bool, alive chan<- struct{}) {
for <-active {
fmt.Print(<-ch, " ")
}
fmt.Print("\n")
close(alive)
}
func main() {
text := "Hello my name is cassava. What is your name? It was nice to meet you!"
manager(strings.Split(text, " "), 3)
}
@cassava
Copy link
Author

cassava commented Jul 1, 2013

@cassava
Copy link
Author

cassava commented Jul 1, 2013

The imports in this gist are only needed for worker, receiver, and main. The pattern itself doesn't require any special imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment