🎯 一、channel 学习全景图
你可以把 channel 学成这 5 层:
基础语法 → 使用模式 → 并发控制 → 底层原理 → 实战设计
🧠 二、第一层:基础语法(必须熟练)
1️⃣ 创建
ch := make(chan int) // 无缓冲
ch := make(chan int, 10) // 有缓冲
2️⃣ 发送 / 接收
ch <- 1 // 发送
x := <-ch // 接收
3️⃣ 关闭
close(ch)
4️⃣ 判断关闭
v, ok := <-ch
5️⃣ range
for v := range ch {
fmt.Println(v)
}
👉 重点:必须 close,否则死循环
⚙️ 三、第二层:核心特性(必须理解)
1️⃣ 阻塞机制(最重要)
👉 channel 的本质是:同步机制
无缓冲 channel
ch := make(chan int)
go func() {
ch <- 1
}()
<-ch
👉 发送必须等接收
有缓冲 channel
ch := make(chan int, 2)
👉 不满不阻塞
2️⃣ FIFO(先进先出)
👉 channel 内部是队列
3️⃣ 单向 channel(面试加分)
func send(ch chan<- int)
func recv(ch <-chan int)
👉 限制方向,提高安全性
🔄 四、第三层:select 多路复用(重点)
select {
case v := <-ch1:
fmt.Println(v)
case ch2 <- 10:
fmt.Println("send")
default:
fmt.Println("no ready")
}
🔥 关键点
-
随机选择一个可执行 case
-
没有 ready:
-
有 default → 执行 default
-
没 default → 阻塞
-
⏱ 超时控制
select {
case <-ch:
case <-time.After(time.Second):
fmt.Println("timeout")
}
🚀 五、第四层:常见使用模式(非常重要)
1️⃣ 生产者-消费者
ch := make(chan int, 10)
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}()
for v := range ch {
fmt.Println(v)
}
2️⃣ worker pool(面试高频)
jobs := make(chan int, 100)
for i := 0; i < 5; i++ {
go func() {
for job := range jobs {
fmt.Println(job)
}
}()
}
3️⃣ fan-in(合并多个 channel)
func fanIn(ch1, ch2 <-chan int) <-chan int
4️⃣ fan-out(广播)
👉 一个 channel → 多个 worker
5️⃣ 通知模式
done := make(chan struct{})
👉 用于结束 goroutine
🧠 六、第五层:底层原理(面试高频)
📦 channel 本质结构
type hchan struct {
buf // 环形队列
sendq // 发送等待队列
recvq // 接收等待队列
lock // 互斥锁
}
📤 发送流程
-
有接收者 → 直接交付
-
有缓冲 → 放入 buffer
-
满了 → 阻塞(进入 sendq)
📥 接收流程
-
有数据 → 直接取
-
有发送者 → 直接拿
-
没数据 → 阻塞(进入 recvq)
🔐 为什么线程安全?
👉 因为:
-
内部加锁
-
调度器控制 goroutine
⚠️ 七、常见问题(必须掌握)
❌ 死锁
ch := make(chan int)
ch <- 1 // 没人接收
❌ goroutine 泄漏
go func() {
<-ch // 永远阻塞
}()
❌ close 使用错误
close(ch)
close(ch) // panic
❌ 向已关闭 channel 发送
👉 直接 panic
⚔️ 八、channel vs mutex(面试必问)
| 对比 | channel | mutex |
|---|---|---|
| 用途 | 通信 | 共享数据 |
| 安全性 | 高 | 需手动控制 |
| 性能 | 稍低 | 更快 |
👉 结论:
简单共享用锁,复杂协作用 channel
🧩 九、学习路径(你可以照着练)
第1步(1天)
-
基本语法
-
阻塞理解
第2步(2天)
-
select
-
timeout
第3步(3天)
-
worker pool
-
producer-consumer
第4步(进阶)
-
goroutine 泄漏
-
context + channel
🔥 十、终极总结(面试王炸)
👉 你可以这样说:
channel 是 Go 提供的 goroutine 通信机制,支持同步和异步传输,通过阻塞保证并发安全,底层由环形队列和等待队列实现,常用于任务调度、并发控制和数据流处理。