Channels pass values between goroutines: ch := make(chan int). Send ch <- v, receive v := <-ch. Unbuffered channels synchronize sender and receiver.
Buffered channels
ch := make(chan string, 2)
ch <- "a"
ch <- "b"
fmt.Println(<-ch)
Buffer size allows sends without immediate receive up to capacity. Close channels with close(ch); range over channel until drained.
Directional types
chan<- int send-only, <-chan int receive-only—API design prevents misuse at compile time.
Important interview questions and answers
- Q: Buffered vs unbuffered?
A: Unbuffered blocks until both sides ready (handoff sync); buffered allows queueing up to capacity. - Q: Send on closed channel?
A: Panics—only sender should close; receivers use comma-ok or range.
Self-check
- How do you create a channel of ints?
- Who should close a channel?
Closing and ranging
Only the sender should close a channel. Receivers detect close with v, ok := <-ch. for v := range ch drains until close—idiomatic worker shutdown.
Leaking goroutines often means a channel was never closed or a receiver exited early—profile with race detector in real projects.
Pitfall: Sending on a closed channel panics—only the sender should close; receivers use range or comma-ok.
Interview prep
- Buffered vs unbuffered?
Unbuffered synchronizes handoff; buffered queues up to capacity before blocking send.
- Who closes channel?
Sender closes—receivers detect close via range or comma-ok; send on closed channel panics.