CodingNeed.

3 · Reliability and project · 25 MIN

Goroutines and channel ownership

A channel transfers values and communicates completion.

A goroutine runs concurrently with other goroutines. In this finite pipeline, the producer sends each result and closes the channel after its final send. The consumer ranges until that close, so main waits for the stream instead of exiting early. An unbuffered send waits for a receiver, which also provides backpressure. This example is finite and always drained; if a real consumer can abandon the stream, add cancellation to every potentially blocked send as in the advanced cancellation workshop.

The producer owns close; cancellation is a separate signal.

Read the example

package main
import "fmt"
func squares(values []int) <-chan int {
  out := make(chan int)
  go func() {
    defer close(out)
    for _, n := range values { out <- n*n }
  }()
  return out
}
func main() { for n := range squares([]int{1,2,3}) { fmt.Println(n) } }
Check the expected output
1
4
9

Your challenge

Add a context parameter and ensure a consumer can cancel after the first value without leaving a blocked sender.

Solution cost: O(n) work and one producer goroutine. time · Account for collection storage separately from the returned result. space

Common trap

Closing a channel from the receiver can panic when its producer sends again.

Study the project implementation
package main
import "fmt"
func squares(values []int) <-chan int {
  out := make(chan int)
  go func() {
    defer close(out)
    for _, n := range values { out <- n*n }
  }()
  return out
}
func main() { for n := range squares([]int{1,2,3}) { fmt.Println(n) } }

Further reading: Official documentation

Next lesson: Project · Validate and summarize expenses

Essential cookies keep your account signed in. Optional analytics is not configured on this site. Your choice does not affect access to lessons.

Read the Privacy Policy. You can change this choice in the footer.