Go

Why is chan struct{} preferred for signaling, and how does close act as a broadcast?

Question 206MediumGo 1.22 to 1.25

struct{} has size 0, so the channel buffer uses no memory for elements, and the type tells the reader that the value means nothing and the event is the point. A send wakes exactly one receiver. A close wakes all current and future receivers, because a receive on a closed channel never blocks. That makes close a one-shot broadcast.

start := make(chan struct{})
var wg sync.WaitGroup
for i := range 10 {
	wg.Add(1)
	go func() {
		defer wg.Done()
		<-start // all 10 park here
		run(i)
	}()
}
close(start) // releases all 10 at once (a "starting gun")
wg.Wait()

This is the basis of context.Done(), errgroup, and shutdown signals. The limitation is that closing is one-shot, since a channel can't be reopened. For repeated broadcasts, swap in a new channel under a mutex (the "generation channel" pattern) or use sync.Cond.Broadcast.

More on Channels & select

All 38 Channels & select questions