Search code examples
gochannelgoroutine

Stop a blocking goroutine


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
}

Solution

  • 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.