Good Code
The good version shows who reads, who writes, who closes the output channel, and how the goroutine exits when the context is canceled.
Lesson 07
Make goroutine lifetime and channel closing ownership explicit so concurrent code can stop cleanly.
func StartWorker(ctx context.Context, jobs <-chan Job, results chan<- Result) {
go func() {
defer close(results)
for {
select {
case <-ctx.Done():
return
case job, ok := <-jobs:
if !ok {
return
}
results <- process(job)
}
}
}()
}func StartWorker(jobs chan Job, results chan Result) {
go func() {
for job := range jobs {
results <- process(job)
}
}()
}
func StopWorker(results chan Result) {
close(results)
}The good version shows who reads, who writes, who closes the output channel, and how the goroutine exits when the context is canceled.
The bad version leaves lifetime implicit and lets a separate function close a channel it does not own.