Channel Direction Scenario
Fast recall
Quick revision
Core answer
Whether you understand Channel Direction Scenario beyond memorized syntax.
Giving a definition without explaining a practical trade-off.
Connect the concept to a small production example and state its complexity or failure mode.
Interview-ready guide
Interview answer
The enforcement:
func producer(out chan<- int) { // send-only — can't receive from out
for i := 0; i < 5; i++ {
out <- i
}
close(out) // close is a SENDER operation — legal on chan<-
}
func consumer(in <-chan int) { // receive-only — can't send to in, can't close
for v := range in {
fmt.Println(v)
}
}
// main creates the bidirectional channel and passes it:
ch := make(chan int)
go producer(ch) // implicit conversion: chan int → chan<- int
go consumer(ch) // implicit conversion: chan int → <-chan intWhat the direction types enforce, via the compiler:
- <-out in producer: compile error (receive on send-only)
- in <- 1 in consumer: compile error (send on receive-only)
- close(in) in consumer: compile error (close is sender-owned)
The conversion is one-way: bidirectional → directional is automatic; directional back to bidirectional is impossible. Once narrowed to a view, the view stays narrow — the caller (holding the bidirectional original) retains all operations.
The API-design pattern: producers return <-chan T (the caller can only consume); consumers accept chan<- T (the caller hands over the feeding rights). The direction in the signature IS the ownership documentation, enforced.
Channel Direction Scenario
Direct Answer
Use directional types in the signatures: producer takes chan<- T (send-only), consumer takes <-chan T (receive-only). The compiler rejects the wrong direction — the contract is in the type.
Deep Dive & Architecture
The mechanics: chan<- T and <-chan T are distinct types in the type system. The conversion (bidirectional → directional) is implicit — the runtime value is unchanged (the same channel pointer), only the compile-time view narrows. The compiler removes the forbidden operations at build time — a direction misuse is a compile error, never a runtime surprise.
The close ownership, formally: close broadcasts 'no more values' to every receiver — a decision only the sender can make (only it knows when production ends). The type system aligns: close is defined on chan<- T and the bidirectional chan T — NOT on <-chan T. A consumer can never close, structurally.
The pattern that composes into pipelines: stage(in <-chan int, out chan<- int) — each stage consumes read-only, produces write-only, and the lifecycle close (defer close(out)) belongs to the stage with the send authority — the channel-direction + close-ownership + defer pattern is the complete Go pipeline discipline.
Common Mistakes & Pitfalls
Giving a definition without explaining a practical trade-off.
Check your understanding
Answer these without looking back at the article.
- How would you compare Channel Direction Scenario with an alternative?
- What is a common mistake when using Channel Direction Scenario?
- When would you use Channel Direction Scenario in a real project?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.