这是我纯手写的《Go语言入门》,手把手教你入门Go。源码+文章,看了你就会🥴!
文章中所有的代码我都放到了github.com/GanZhiXiong/go_learning这个仓库中!
看文章时,对照仓库中代码学习效果更佳哦!
带缓冲通道
带缓冲通道(buffered channel)是一种在被接收前能存储一个或多个值的通道。
- 这类通道并不强制要求goroutine之间必须同时完成发送和接收
- 只有在通道中没有要接收的值时,接收动作才会阻塞
- 只有在通道没有可用缓冲区容纳被发送的值时(存储空间满时),发送动作才会阻塞
作用
无缓冲通道保证收发过程同步。
无缓冲收发过程类似于快递员给你电话让你下楼取快递,整个递交快递的过程是同步发生的,你和快递员不见不散。
但这样做快递员就必须等待所有人下楼完成操作后才能完成所有投递工作。
如果快递员将快递放入快递柜中,并通知用户来取,快递员和用户就成了异步收发过程,效率可以有明显的提升。带缓冲的通道就是这样的一个“快递柜”。
创建带缓冲通道
通道实例 := make(chan 通道类型, 缓冲大小)
- 缓冲大小:就是channel可用存储多少元素,如果缓冲大小为2,就是可以存储2个元素。该通道写入前2个元素是无阻塞的,但是写入第3个元素时,代码会阻塞,直到其他协程从通道中读取一些元素,腾出空间才行。
- 缓冲大小为0是无缓冲通道
- 缓冲大小大于0是带缓冲通道
示例1
func TestBufferedChan(t *testing.T) {
ch := make(chan int, 3)
t.Log(ch, len(ch), cap(ch))
ch <- 1
ch <- 2
ch <- 3
// 下面打开取消注释,则会报错:fatal error: all goroutines are asleep - deadlock!
// 因为通道只能存储3个元素
//ch <- 4
t.Log(ch, len(ch), cap(ch))
t.Log(<-ch)
t.Log(<-ch)
t.Log(<-ch)
// 因为通道内的元素都已经取出,所以运行后报错:fatal error: all goroutines are asleep - deadlock!
//t.Log(<-ch)
t.Log(ch, len(ch), cap(ch))
}
=== RUN TestBufferedChan
29_buffered_channel_test.go:11: 0xc000108100 0 3
29_buffered_channel_test.go:20: 0xc000108100 3 3
29_buffered_channel_test.go:22: 1
29_buffered_channel_test.go:23: 2
29_buffered_channel_test.go:24: 3
29_buffered_channel_test.go:28: 0xc000108100 0 3
--- PASS: TestBufferedChan (0.00s)
PASS
示例2
func TestBufferedChan1(t *testing.T) {
response := make(chan string, 3)
// 同时向3个站点发起请求,request是一个阻塞的方法,需要等待服务的响应
go func () { response <- request("mirror1")}()
go func () { response <- request("mirror2")}()
go func () { response <- request("mirror3")}()
// main goroutine则接受最快的响应,其他响应不接收
t.Log(<-response)
t.Log(<-response)
t.Log(<-response)
}
func request(mirror string) string{
if mirror == "mirror1"{
time.Sleep(5 * time.Second / 10) // 通过sleep模拟请求和响应在网络中传输的时间和服务器处理请求的时间
}else if mirror == "mirror2"{
time.Sleep(3 * time.Second / 10)
}else if mirror == "mirror3"{
time.Sleep(7 * time.Second / 10)
}
return "response from " + mirror
}
=== RUN TestBufferedChan1
29_buffered_channel_test.go:40: response from mirror2
29_buffered_channel_test.go:41: response from mirror1
29_buffered_channel_test.go:42: response from mirror3
--- PASS: TestBufferedChan1 (0.70s)
PASS
支持🤟
- 🎸 [关注❤️我吧],我会持续更新的。
- 🎸 [点个👍赞吧],码字不易麻烦了。