package main import ( "bufio" "fmt" "os" "time" ) const numWorkers = 3 var ( workers chan bool requests chan string ) // worker executes requests. func worker(id int) { for { switch r := <-requests; r { case "sleep": fmt.Println(id, "sleeping") time.Sleep(5 * time.Second) case "echo": fmt.Println(id, "echo") case "quit": os.Exit(0) default: panic(fmt.Sprintf("%v unkown command %q", id, r)) } } } // run runs a function and catches any panic. func run(f func(int), id int) { defer func() { if rec := recover(); rec != nil { fmt.Println("restarting failed worker: ", rec) } workers <- true }() f(id) } // monitor ensures that as numWorkers goroutines are running // at any time. func monitor() { workers = make(chan bool, numWorkers) for i := 0; i < cap(workers); i++ { workers <- true } id := 0 for _ = range workers { id++ go run(worker, id) } } // reader reads lines from stdin and puts them in the requests channel. func reader() { requests = make(chan string) s := bufio.NewScanner(os.Stdin) for s.Scan() { requests <- s.Text() } } func main() { go monitor() reader() }