Best way to stop a single goroutine?

Issue

In my program I have several go-routines who are essentially running endless processes. Why? you may ask, long story short it is the purpose of my entire application so it’s out of question to change that. I would like to give users the ability to stop a single go-routine. I understand that I can use channel to signal the go-routines to stop, however there may be cases where I have, say, 10 go-routines running and I only want to stop 1. The issue is that the number of go-routines I want to run is dynamic and based on user input. What is the best way for me to add the ability to stop a go-routine dynamically and allow for singles to be stopped without the rest?

Solution

You need design a map to manage contexts.

Assume you’ve already known usage of context. It might look like:

ctx, cancel := context.WithCancel(ctx.TODO())

go func(ctx){
    for {

        select {

           case <-ctx.Done():
                return
           default:
              // job
        }
    }
}(ctx)

cancel()

Ok, now you can convert your question to another, it might called ‘how to manage contexts of many goroutine’

type GoroutineManager struct{
    m sync.Map
}
func (g *GoroutineManager) Add(cancel context.CancelFunc, key string)) {
    g.m.Store(key, cancel)
}

func (g *GoroutineManager) KillGoroutine(key string) {
    cancel, exist := g.m.Load(key)
    if exist {
        cancel()
    }
}

Ok, Now you can manage your goroutine like :

ctx, cancel := context.WithCancel(ctx.TODO())

manager.Add(cancel, "routine-job-1")
go func(ctx){
    for {

        select {

           case <-ctx.Done():
                return
           default:
              // job
        }
    }
}(ctx)


// kill it as your wish
manager.KillGoroutine("routine-job-1")

Answered By – fwhez

Answer Checked By – Gilberto Lyons (GoLangFix Admin)

Leave a Reply

Your email address will not be published.