I indeed had the same question and came up with this approach:
https://play.golang.org/p/9F9T_sYIof
Using: context.WithTimeout(context.Background(), 10*time.Second):
https://play.golang.org/p/WK0ebe0c9t
Don't know if is the proper way of doing it but is working:
package main
import (
"context"
"fmt"
"sync"
"time"
)
func doWork(element int, wg *sync.WaitGroup) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second))
defer cancel()
ch := make(chan struct{})
go func() {
time.Sleep(time.Second)
fmt.Printf("element = %+v\n", element)
ch <- struct{}{}
}()
select {
case <-ch:
case <-ctx.Done():
fmt.Println(ctx.Err())
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
elements := []int{1, 2, 3}
for _, element := range elements {
wg.Add(1)
go doWork(element, &wg)
}
wg.Wait()
}
Notice the goroutine within the doWork function:
go func(ch chan struct{}) {
// your code logic goes here
}(ch)
That's the part that I don't know if is the best way of doing it, but seems to be the pattern to follow when using context mainly when want to deal with the ctx.Done()