Includes solved 02-worker-pool and 09-safe-counter (mutex, atomic, sharded). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GbnJj9ZqEx9nUvzkjdwfMq
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
// Exercise 07 — Fan-in / Merge Channels
|
|
//
|
|
// ASSIGNMENT
|
|
// ----------
|
|
// Implement Merge(ctx, chs...):
|
|
//
|
|
// 1. Returns a single channel carrying every value from every input channel.
|
|
// 2. The output channel is CLOSED once all input channels are closed and
|
|
// drained.
|
|
// 3. If ctx is cancelled, Merge stops forwarding, and all its internal
|
|
// goroutines exit even if inputs never close and even if nobody reads
|
|
// the output anymore. (No goroutine leaks — the tests count goroutines.)
|
|
// 4. Order across inputs is unspecified.
|
|
//
|
|
// Run the tests: go test -race ./07-fan-in/
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// Merge fans in all input channels into one output channel.
|
|
// TODO: implement me.
|
|
func Merge[T any](ctx context.Context, chs ...<-chan T) <-chan T {
|
|
out := make(chan T)
|
|
// TODO:
|
|
// - one forwarder goroutine per input channel
|
|
// - each forward is a select: {out <- v} vs {<-ctx.Done()}
|
|
// - reading the input must ALSO select on ctx.Done()
|
|
// - closer goroutine: wg.Wait(); close(out)
|
|
return out
|
|
}
|
|
|
|
func main() {
|
|
gen := func(vals ...int) <-chan int {
|
|
ch := make(chan int)
|
|
go func() {
|
|
defer close(ch)
|
|
for _, v := range vals {
|
|
ch <- v
|
|
}
|
|
}()
|
|
return ch
|
|
}
|
|
for v := range Merge(context.Background(), gen(1, 2, 3), gen(10, 20), gen(100)) {
|
|
fmt.Println(v)
|
|
}
|
|
}
|