// lesson: channels
Channels
Channels connect goroutines: one sends, another receives. Unbuffered channels synchronize both sides โ a send blocks until a receiver is ready.
ch := make(chan int)
go func() { ch <- 42 }()
fmt.Println(<-ch) // 42
Close a channel to signal "no more values". Receivers can range over a channel until it is closed. Only the sending side should close a channel โ closing an already-closed channel, or sending on a closed one, panics.
A receive can also ask whether the channel is still open:
v, ok := <-ch // ok is false once ch is closed and drained
ok is false only once the channel is both closed and drained โ every
value sent before the close has already been received; v is the zero
value in that case.
Reading from multiple channels: select
select lets a goroutine wait on more than one channel operation at once.
It blocks until one case is ready, then runs that case; if several are
ready at the same time, it picks one at random. Combined with the
comma-ok form above, select can read from two channels until both are
drained, retiring whichever one closes first:
for a != nil || b != nil {
select {
case v, ok := <-a:
if !ok {
a = nil // never selects again โ a nil channel blocks forever
continue
}
fmt.Println("from a:", v)
case v, ok := <-b:
if !ok {
b = nil
continue
}
fmt.Println("from b:", v)
}
}
Setting a drained channel variable to nil is the trick that retires it:
a receive on a nil channel never becomes ready, so select simply stops
considering that case and keeps servicing the other one.
โบ Fan In
15 ptsImplement Merge(a, b <-chan int) <-chan int returning a channel that yields
every value from both inputs and closes when both are exhausted.
Log in to submit a solution and earn points.