What are directional channel types and why use them?
Question 197MediumGo 1.22 to 1.25
chan<- T is send-only and <-chan T is receive-only. A bidirectional chan T converts implicitly to either one, but you can't convert back. The compiler rejects receiving from a send-only channel and sending to a receive-only one. It also rejects close on a receive-only channel, which enforces "the receiver never closes".
func producer(out chan<- int) {
defer close(out) // allowed: sender side
for i := range 3 { out <- i }
}
func consumer(in <-chan int) {
for v := range in { fmt.Println(v) }
// close(in) // compile error: cannot close receive-only channel
}
func main() {
ch := make(chan int)
go producer(ch)
consumer(ch)
}
Why it matters: the types document ownership in the API. A function that returns <-chan T (the generator pattern) keeps the ability to send and close to itself. Read the arrow as binding to the leftmost chan: chan<- chan int is a send-only channel of bidirectional channels, while chan (<-chan int) needs parentheses.
More on Channels & select
- Q195What does this program do? (unbuffered send in main)
- Q196How does
for rangeover a channel work, and what are its pitfalls? - Q198How do you implement a timeout on a channel operation? Compare
time.After,time.NewTimer, andcontext. - Q199Does
time.Afterin a loop leak memory? How did Go 1.23 change this? - Q200What's the difference between
time.Tickerand repeatedtime.After? What happens if the consumer is slow? - Q201How do you do a non-blocking send or receive?