Who should close a channel, and why? What are the rules?
Question 188MediumGo 1.22 to 1.25
The rule: the sender closes, never the receiver, and only when there are no more sends. Closing is a broadcast message that says "no more values". A receiver closing the channel would cause a sender panic (send on closed channel) and races with in-flight sends.
- One sender: that sender closes, usually with
defer close(out). - Many senders: no single sender may close. Use a coordinator: a
sync.WaitGroupand a separate goroutine that waits and then closes. - Receivers wanting to stop senders: don't close the data channel. Signal through a separate
donechannel orcontext. - Closing is not required for garbage collection. An unreferenced channel is collected whether it is closed or not. Close only when receivers need the signal, for example to end a
range.
func merge[T any](cs ...<-chan T) <-chan T {
out := make(chan T)
var wg sync.WaitGroup
for _, c := range cs {
wg.Add(1)
go func() {
defer wg.Done()
for v := range c {
out <- v
}
}()
}
go func() { wg.Wait(); close(out) }() // single owner closes
return out
}More on Channels & select
- Q186What does this print? (receiving from a closed buffered channel)
- Q187Explain the comma-ok idiom on channel receive. When is it needed and when is
for rangebetter? - Q189How do you safely close a channel that might be closed by multiple goroutines?
- Q190How does
selectchoose among multiple ready cases? Is it fair? - Q191How do you implement a priority select in Go?
- Q192Why is a nil channel useful in a
select? Show an example.