A first-class object can be handled like an ordinary value: stored in a variable, passed to or returned from a function, and even sent on a channel. In Go, channels have this property. That makes a channel-producing function more than a one-off worker: its returned channel can become an input to later concurrent operations. section 8.1.1 section 9.0
This flexibility supports message-passing designs in which goroutines keep isolated state rather than sharing memory directly. Instead of fixing every connection in advance, a program can pass channels through functions and alter the structure of its communicating processes while it runs. section 9.1.2 section 9.4
First-class channels enable several practical design moves:
- Return an output-only channel from a goroutine-creating function, so callers can reuse it as a building block. section 8.1.1
- Accept channels as function parameters, allowing pipeline stages to be connected without sharing state. section 9.4
- Pass a channel on another channel, enabling a pipeline to grow as new work requires new stages. section 9.2.7
- Create or remove channels at runtime when program logic needs a different process topology. section 9.1.2
Returning channels for select
A writeEvery function creates a string channel, starts an anonymous goroutine, periodically sends a message, and returns that channel. Calling it twice produces independent Tick and Tock streams. A select then blocks until either returned channel has a message; if multiple cases are ready, the selected case is random, so code must not depend on case order. section 8.1.1
Listing 9.20 The primeMultipleFilter() goroutine
package main import "fmt" func primeMultipleFilter(numbers <-chan int, quit chan<- int) { var right chan int p := <-numbers #1 fmt.Println(p) #1 for n := range numbers { #2 if n%p != 0 { #3 if right == nil { #4 right = make(chan int) #4 go primeMultipleFilter(right, quit) #4 } right <- n #5 } } if right == nil { close(quit) #6 } else { close(right) #7 } } #1 Receives the first message containing the prime number p on the input channel and prints it #2 Reads the next number from the input channel #3 Discards any received number that is a multiple of p #4 If the current goroutine has no right, it starts a new goroutine and connects to it with a channel. #5 Passes the filtered number to the right channel #6 Closes the quit channel if there are no more numbers to filter and the goroutine has no right channel #7 Otherwise, closes right channel
The prime filter keeps its downstream channel in a variable. On the first non-multiple, it creates that channel and passes it to a new filter goroutine, extending the pipeline only when needed. section 9.2.7






