Closing Channels
Close a channel to broadcast completion; only senders should close.
Closing a channel signals that no more values will be sent. All receivers immediately unblock and receive the zero value with an ok of false.
Use close(ch) after sending all values. A receiver can detect the close with the comma-ok idiom: v, ok := <-ch. When ok is false the channel is closed and drained.
package main
import "fmt"
func main() {
jobs := make(chan int, 5)
for i := 1; i <= 3; i++ {
jobs <- i
}
close(jobs) // signal: no more jobs
for {
j, ok := <-jobs
if !ok {
fmt.Println("channel closed")
break
}
fmt.Println("received job", j)
}
}A for range loop over a channel automatically stops when the channel is closed - the comma-ok check is implicit:
for j := range jobs {
fmt.Println("job", j)
}
// loop exits when jobs is closedClosing a channel that was already closed panics at runtime. Use a sync.Once when multiple goroutines might attempt to close the same channel:
var once sync.Once
closeJobs := func() {
once.Do(func() { close(jobs) })
}In production
Closing a channel is a broadcast signal - all receivers see the close immediately. Only the goroutine responsible for producing values should close the channel; closing from a receiver or a third party is a race condition. Use a sync.Once or a dedicated closer goroutine when multiple producers share one channel.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free