Skip to content

Instantly share code, notes, and snippets.

@vmosoti
Forked from campoy/letitfail.go
Created May 4, 2019 05:34
Show Gist options
  • Save vmosoti/6011fe6dd06a1b1b45af875cada39ed5 to your computer and use it in GitHub Desktop.
Save vmosoti/6011fe6dd06a1b1b45af875cada39ed5 to your computer and use it in GitHub Desktop.
This example shows how to have a set of goroutines running concurrently and processing requests. Panics from goroutines are recovered and the worker is restarted. You can download it and run it directly using `go run letitfail.go`
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()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment