-3

How can I kill a goroutine which is blocking. An idea is that returning from the host function would be a solution but I'm not sure if this kills the goroutine or not.

func myFunc() int {
   c := make(<-chan int)
   go func(){
      for i := range c {
      // do stuff
      }
   }()
   return 0 // does this kills the inner goroutine?
}

Is there a more nice solution? For example it would be nice that something like this work but because of the blocking for it doesn't:

func myFunc() int {
   c := make(<-chan int)
   closeChan := make(chan int)
   go func() {
      select {
      case close := <-closeChan:
         return 0
      default:
         for i := range c {
            // do stuff
         }
      }
   }()
   closeChan<-0
   // other stuff
}
  • 2
    See also, https://stackoverflow.com/questions/51941132/how-to-kill-goroutines, https://stackoverflow.com/questions/41148357/force-kill-goroutine-after-timeout, https://stackoverflow.com/questions/43035331/how-to-cancel-goroutines-after-certain-amount-of-time, https://stackoverflow.com/questions/48763833/cancel-currently-running-function-goroutine, https://stackoverflow.com/questions/28240133/cancel-a-blocking-operation-in-go, https://stackoverflow.com/questions/51223062/goroutine-timeout, https://stackoverflow.com/questions/41148357/force-kill-goroutine-after-timeout, and so on – JimB Dec 10 '19 at 14:39
  • @JimB some of those have no answers at all, making them useless references, they just serve to prove the point that this is a common question, which isn't actually helpful. Also none of those answer *this* question - they answer the title maybe, but not the actual post. – Adrian Dec 10 '19 at 14:58
  • @Adrian: which is why I didn't close this as a duplicate ;) They do serve as a reference (though I admit I didn't read through them all, which is why I posted a plethora of choices), as they may have comments, links to other questions, or rephrasing of the question, any of which might help enlighten someone lacking a basic understanding of concurrency patterns in go. OP can choose to read through other related problems and solutions, or not. It also serves to fill out the "Linked" sections in the questions, to help others traverse through related issues. – JimB Dec 10 '19 at 15:00

1 Answers1

1

You can't kill a goroutine from outside - you can't even reference a specific goroutine; nor can you abort a blocking operation. You can, however, move the for to the outside:

go func() {
   for  {
       select {
       case close := <-closeChan:
          return 0
       case i,ok := <-c:
         // do stuff
         if !ok {
             // channel is closed & empty
             return 0
         }
       }
   }
}()

This will loop forever, and each iteration it will wait for a message on both channels; whichever gets a message first will be processed, then the loop repeats. This is a very common pattern in Go.

Adrian
  • 42,911
  • 6
  • 107
  • 99
  • is `i := <- c` excatly identical to `i := range c`? I think the second one receives messages even after closing the channel but the first one doesn't. – John Milner Dec 10 '19 at 14:31
  • That's true, sorry - getting ahead of myself. Fixed! – Adrian Dec 10 '19 at 14:33
  • Thank you. The word first and second in my comment are misused too! – John Milner Dec 10 '19 at 14:41
  • So for my final assurance, is `i,ok := <- channel` (and checking `ok`) style of reading channels identical to `i := range channel`? – John Milner Dec 10 '19 at 14:44
  • I'm not sure what you mean by "identical" - they're equivalent, the differences are basically what you see here and noted in your comment. It does the same thing in a different way, it's more verbose but it allows you to use `select`. – Adrian Dec 10 '19 at 14:52