通道的使用

通道使用后需要关闭

通道中的数据是占用资源的,使用后及时关闭通道,可以保护数据安全,防止资源泄露;以及可以提高程序的性能,避免资源浪费

未关闭通道的风险

1、通道中的资源可能会泄露

2、持续占用系统资源,导致性能下降

3、遍历一个不关闭的channel会造成死循环

如何优雅的关闭通道?

  • 使用Go通道的一个基本原则:不要在接收方关闭通道,确保关闭通道的是唯一发送方

  • 不要关闭(或者发送值到)已经被关闭了的通道

简单粗暴的关闭方案:defer close(chanName)

礼貌一点:使用``sync.Once`

type MyChannel struct {
	C    chan T
	once sync.Once
}
func NewMyChannel() *MyChannel {
	return &MyChannel{C: make(chan T)}
}
func (mc *MyChannel) SafeClose() {
	mc.once.Do(func() {
		close(mc.C)
	})
}

也可以使用``sync.Mutex`避免多次关闭同一通道

type MyChannel struct {
	C      chan T
	closed bool
	mutex  sync.Mutex
}
func NewMyChannel() *MyChannel {
	return &MyChannel{C: make(chan T)}
}
func (mc *MyChannel) SafeClose() {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	if !mc.closed {
		close(mc.C)
		mc.closed = true
	}
}
func (mc *MyChannel) IsClosed() bool {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	return mc.closed
}

优雅的关闭方案:使用sync.WaitGroup

情况1:单生产者,单消费者

  • 直接让生产者关闭channel即可

情况2:单生产者,多消费者

  • 同样直接让生产者关闭channel即可

情况3:多生产者,单消费者

  • 让接收者关闭一个额外的通知通道来告知发送者停止发送

情况4:多生产者,多消费者

  • 引入一个信号通道,用于通知所有的生产者和消费者停止工作

有缓存和无缓存通道的区别

无缓冲

无缓冲通道在赋值后不读取就会进入阻塞

发送和接收的交互行为是同步的,且无法单独存在

有缓冲

有缓冲通道赋值后,值会进入缓冲区,在缓冲区满后阻塞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值