29《Go语言入门》带缓冲通道

这是我纯手写的《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

支持🤟


  • 🎸 [关注❤️我吧],我会持续更新的。
  • 🎸 [点个👍赞吧],码字不易麻烦了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值