“Sometimes my Go channel waits... sometimes it doesn’t. What’s happening?”
If Go channels were pipes, then the difference is:
Unbuffered channel = No bucket. Pass stuff directly.
Buffered channel = There’s a bucket in between!
Let’s break it down.
These are the default:
ch := make(chan string)Sender waits until receiver is ready
Receiver waits until sender sends something
func main() {
ch := make(chan string)
go func() {
ch <- "hello"
}()
msg := <-ch
fmt.Println(msg)
}✅ Works because both are there, like a handshake!
If one is missing — program hangs forever.
Create it with a size:
ch := make(chan string, 3)Now it can hold 3 messages before sender has to wait.
“Hey, just drop your message in this box. I’ll check later.”
func main() {
ch := make(chan string, 2)
ch <- "one"
ch <- "two"
// Can keep going! No receiver needed yet
fmt.Println(<-ch)
fmt.Println(<-ch)
}ch := make(chan string)
ch <- "hi" // ❌ Will hang if no one’s receiving!ch := make(chan string, 2)
ch <- "1"
ch <- "2"
ch <- "3" // ❌ Will hang! Buffer fullYou want synchronization
Receiver and sender must meet before moving on
You want some flexibility
You’re okay sending things in advance
You’re batching, or working with pipelines
len(ch) // current number of items
cap(ch) // capacity of bufferExample:
ch := make(chan string, 5)
ch <- "a"
fmt.Println(len(ch)) // 1
fmt.Println(cap(ch)) // 5Channel Type | Blocking? | Buffer?
Unbuffered | Yes (on send/recv) | ❌
Buffered | Only when full/empty | ✅That’s buffered vs unbuffered 🎯
Simple, right?
No posts

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.