You could use Golang context. Here's some of my code when I was learning it.
package main
import (
"fmt"
"log"
"time"
"golang.org/x/net/context"
)
func main() {
someHandler()
}
func someHandler() {
//Create a new context with a timeout duration of six seconds. You also get a cancel function you can call early.
//You can also have context end at a certain time, instead of a timeout
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(6))
for i := 0; i < 5; i++ {
go doStuff(ctx, i)
}
select {
case <- ctx.Done():
log.Println("Got a cancel request")
return
case <-time.After(time.Second * time.Duration(5)):
//Here I'm actually ending it earlier than the timeout with cancel().
log.Println("Timed out")
cancel()
}
}
func doStuff(ctx context.Context, num int) {
for {
select {
case <-ctx.Done():
fmt.Println("Done working")
return
default:
fmt.Println("go", num, "working")
}
time.Sleep(time.Second)
}
}
Outputs:
$ go run app.go
go 0 working
go 4 working
go 2 working
go 3 working
go 1 working
go 1 working
go 0 working
go 4 working
go 3 working
go 2 working
go 0 working
go 4 working
go 2 working
go 1 working
go 3 working
go 4 working
go 3 working
go 0 working
go 2 working
go 1 working
go 3 working
go 4 working
go 1 working
go 0 working
go 2 working
2016/10/01 23:25:23 Timed out