I have a pool of goroutines which I want to kill a specific one of them from outside.
Thanks for your help
I have a pool of goroutines which I want to kill a specific one of them from outside.
Thanks for your help
You cannot "kill" a goroutine. You can use one of the synchronizations primitives, or the context to tell the goroutine that you want it to end.
ctx,cancel:=context.WithCancel(context.Background())
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default
}
// Do stuff
}
}(ctx)
...
// Tell that goroutine to stop
cancel()
You can use sync.atomic as well:
die:=make([]int32,nGoroutines)
go func(i int) {
if atomic.LoadInt32(&die[i])==1 {
return
}
// Do stuff
if atomic.LoadInt32(&die[i])==1 {
return
}
// Do more stuff
}(0) // 0'th goroutine
...
// Tell goroutine n to stop
atomic.StoreInt32(&die[n],1)
I found an answer. There is a concept named Context which carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes. This is sample codes:
type Job struct {
ID int
Context context.Context
Cancel context.CancelFunc
}
var jobs = make(map[int] Job)
func worker(ctx context.Context, index int) {
fmt.Printf("starting job with id %d\n", index)
<-ctx.Done()
}
func main() {
var err error
id := 0
r := gin.Default()
r.POST("/start", func(c *gin.Context) {
var job Job
err := json.NewDecoder(c.Request.Body).Decode(&job)
if err != nil{ fmt.Println(err)}
ctx, cancel := context.WithCancel(context.Background())
job.ID = id
job.Context = ctx
job.Cancel = cancel
jobs[job.ID] = job
c.JSON(http.StatusOK, gin.H{"message": "job received"})
go worker(ctx, job.ID)
id ++
})
r.GET("/cancel/:id", func(c *gin.Context) {
id := c.Param("id")
idInt, err := strconv.Atoi(id)
if err != nil {fmt.Println(err)}
jobs[idInt].Cancel()
})
err = endless.ListenAndServe(":8080", r)
if err != nil{ fmt.Printf("Could not run server : %v", err.Error())}
}
You could use a channel
endRoutine:= make(chan bool)
go func() {
<-endRoutine
}()
//To end one thread waiting on the channel
endRoutine<-true
https://play.golang.org/p/IRARfywOLZX
If you are processing data in a loop and need to check if you should exit on each iteration, you can use a switch
go func() {
for {
switch {
case <-endRoutine:
return //exit
default:
break
}
}
}()