Also: you can use the same context for all the workers (if that's 
appropriate); or if you want each worker to have a different context, you 
can make those contexts children of the same top-level context.  In that 
case, you only need to cancel one context and all the workers will stop, 
without having to keep a map of them.

Do bear in mind that you may wish to wait for the workers to finish what 
they're currently doing, before the program exits.  One way to do that is 
with a sync.WaitGroup, which you increment before starting each worker, and 
each worker decrements just before it terminates.  Then in your main 
program you wait on the WaitGroup.

Typical pattern: https://play.golang.org/p/51oy7ySbL4T

On Monday, 30 August 2021 at 10:01:08 UTC+1 Ian Davis wrote:

>
> On Sun, 29 Aug 2021, at 10:45 PM, sansaid wrote:
>
> Hello,
>
> Does anybody know of some reference code or common patterns I can use to 
> keep track of worker goroutines? For context, I want a user to be able to 
> issue a "stop" command using a CLI tool which will prompt my server to 
> gracefully terminate one of my workers. 
>
> For example, when a user issues a "start" command through a CLI tool, this 
> will signal my server to spawn a goroutine that perpetually runs and polls 
> an HTTP endpoint until a user initiates a "stop" command. When the user 
> issues a "stop" command through the same CLI tool, I want the server to be 
> able to signal the goroutine to stop. Any reference code would be much 
> appreciated!
>
> One approach I thought of was by passing a `context.WithCancel()` and 
> holding a reference to the cancel function in a global map (with the worker 
> ID as keys). When the user issues a "stop" command against the worker ID, 
> another function is executed which calls the context's cancel function. 
> Example code below (appreciate this is horrendously breaking a lot of 
> rules, but I want to focus only on the elements around passing the cancel 
> function around - happy to discuss anything else that is of concern to 
> someone though):
>
> ```
> // invoked when a CLI start subcommand is issued to my main CLI tool
> func (w *WorkerGroup) Start(ctx context.Context, id string) {
>   _, cancel := context.WithCancel(ctx)
>
>   w.Workers.Lock()
>   w.Workers[id] := cancel
>   w.Workers.Unlock()
>
>   go startWorker(id)
> }
>
> // invoked when a CLI stop subcommand is issued to my main CLI tool
> func (w *WorkerGroup) Stop(id string) {
>   cancelWorker := w.Workers[id]
>
>   cancelWorker()
> }
> ``` 
>
> I have read that passing a context's cancel function around is a bad idea, 
> but in an example like this, is it justified?
>
>
> Passing the cancel function is fine and storing it for use later is fine 
> too.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/fdff94c4-c0e4-4418-abb3-eba91298fbb7n%40googlegroups.com.

Reply via email to