golang channel的有缓冲和无缓冲的区别
·
一:先打个比方:快递柜和当面签收
想象你要给朋友送一个礼物:
无缓冲 channel = 当面签收(必须同时在场)
你拿着礼物站在朋友家门口,必须等他开门出来,你亲手把礼物交到他手上,你才能离开。
如果他不在家,你就一直等着(阻塞)
他必须亲自来拿,你们必须同时在场
有缓冲 channel = 快递柜(不用同时在场)
你把礼物放进快递柜,然后就可以走了。朋友什么时候有空,自己来取。
如果柜子满了,你就放不进去了,得等着(阻塞)
如果柜子是空的,朋友取了也没东西,也得等着
二:代码示例(超级简单版)
无缓冲:必须同时准备好
package main
import "fmt"
func main() {
// 创建一个无缓冲 channel(像当面签收)
ch := make(chan string)
// 朋友在另一个房间等着收礼物
go func() {
gift := <-ch // 朋友等着收礼物
fmt.Println("朋友收到:", gift)
}()
// 你送礼物(必须等朋友准备好)
fmt.Println("你送出礼物")
ch <- "一个蛋糕"
fmt.Println("你离开了")
}
输出:
你送出礼物
朋友收到: 一个蛋糕
你离开了
关键:你送礼物的时候,如果朋友还没准备好,你会一直等。
有缓冲:可以放快递柜
package main
import "fmt"
func main() {
// 创建一个有缓冲 channel,柜子能放2个礼物
ch := make(chan string, 2)
// 你直接往柜子里放礼物,不用等朋友
fmt.Println("你放第一个礼物")
ch <- "蛋糕"
fmt.Println("你放第二个礼物")
ch <- "鲜花"
// 柜子满了,再放就要等了
// ch <- "第三个" // 这行会报错(死锁)
// 朋友有空了来取
fmt.Println("朋友取到:", <-ch)
fmt.Println("朋友取到:", <-ch)
}
输出:
你放第一个礼物
你放第二个礼物
朋友取到: 蛋糕
朋友取到: 鲜花
关键:你不用等朋友,直接放进去就走,他晚点来拿。
三:一张图看懂区别
无缓冲 channel(当面给):
你 -----(等)-----> 朋友(必须同时)
(直接交接)
有缓冲 channel(快递柜):
你 --(放)--> [柜子] --(取)--> 朋友
(有缓冲区)
四:什么时候用哪个?
| 场景 | 用哪种 | 为什么 |
|---|---|---|
| 通知朋友"我到了" | 无缓冲 | 必须确认他听到了 |
| 做任务时限制同时人数 | 有缓冲 | 放令牌到柜子里,用完放回 |
| 生产蛋糕,消费者慢慢吃 | 有缓冲 | 生产快消费慢,用柜子缓冲 |
| 两件事必须同步完成 | 无缓冲 | 必须手拉手一起做 |
五:最容易犯的错
错误1:无缓冲时没人接收就发送
ch := make(chan int)
ch <- 5 // 死锁!因为没人接收
就像你拿着礼物站在门口,但朋友根本不在家,你就永远等下去。
错误2:有缓冲时忘记检查容量
ch := make(chan int, 1) // 只能放1个
ch <- 10
ch <- 20 // 死锁!柜子满了
就像快递柜只有一个格子,你想放两个进去,第二个放不进去,只能干等。
六:最简记忆法
无缓冲 = 必须两个人同时在线,才能发消息
有缓冲 = 可以发消息到"收件箱",对方有空再看
更多推荐


所有评论(0)