Skip to content

Instantly share code, notes, and snippets.

@campoy
Last active January 6, 2024 07:26
  • Star 34 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save campoy/6217854 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()
}
@O136
Copy link

O136 commented Mar 29, 2019

minor thing:
for range workers {...}
instead of
for _ = range workers {...}

@mytholog
Copy link

go run --race letitfail.go
==================
WARNING: DATA RACE
Read at 0x00000120cfe0 by goroutine 7:
...

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