// 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 pts

Implement 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.