Search code examples
gochannelgoroutine

closing channel quits multiple go routines?


Given this code:

package main

import (
  "fmt"
  "time"
)

func first(quit chan error) {
  fmt.Println("1")
  for {
    select {
    case <-quit:
      fmt.Println("first quits")
      return
    default:
      time.Sleep(20 * time.Millisecond)
    }
  }
}

func second(quit chan error) {
  fmt.Println("2")
  for {
    select {
    case <-quit:
      fmt.Println("second quits")
      return
    default:
      time.Sleep(20 * time.Millisecond)
    }
  }
}

func main() {
  quit := make(chan error)
  go first(quit)
  go second(quit)
  //something happens here, let's just simulate with a sleep
  time.Sleep(500 * time.Millisecond)
  close(quit)
  time.Sleep(500 * time.Millisecond)
}

It seems that closing a channel correctly terminates two independent go routines. I thought channels were 1:1 communication paths, I was first trying to write an error into the quit channel but then only one of the go routines would be reading it. So I was reading all sorts of fan-out strategies until it occurred to me that closing the channel might just work.

Is closing the channel in this way the correct method to terminate independent go routines?


Solution

  • Reading from a closed channel always succeeds. Because of this, closing a channel is usually used to broadcast all goroutines that read from that channel that something has happened (timeout, cancel request, etc).

    To answer your question: test, closing a channel is a correct way to let all goroutines know that it is time to terminate. That is what context.Context does when it is canceled.