golang channel 封装

对于closed或nil通道,规则如下:

  • 无论收发,nil通道都会阻塞。
  • 不能关闭nil通道。
  • 重复关闭通道,引发panic !
  • 向已关闭通道发送数据,引发 panic!
  • 从已关闭通道接收数据,返回缓冲数据或零值。

nil通道是指没有make的变量。鉴于通道关闭后,所有基于此的阻塞都被解除,可用作通知。

没有判断通道是否已被关闭的直接方法,只能透过收发模式获知,

操作 已关闭的channel nil channel
如果channel中还有数据,可以继续读取;如果channel中没有数据了, 可以读到零值 永久阻塞(deadlock)
panic: send on closed channel 永久阻塞(deadlock)
close panic: close of closed channel panic: close of nil channel

为避免重复关闭,可包装close函数。也可以类似方式封装send recv 操作。

func closechan[T any](c chan T) {
	defer func(){
		recover()
	}()

	close(c)
}

func main() {
	c := make(chan int, 2)

	closechan(c)
	closechan(c)
}

可使用 sync.RWMutex、sync.Once 优化设计。

type Queue[T any] struct {
	sync.Mutex	

	ch     chan T
	cap    int
	closed bool
}

func NewQueue[T any](cap int) *Queue[T] {
	return &Queue[T]{
		ch: make(chan T, cap),
	}
}

func (q *Queue[T]) Close() {
	q.Lock()
	defer q.Unlock()

	if !q.closed {
		close(q.ch)
		q.closed = true
	}
}

func (q *Queue[T]) IsClosed() bool {
	q.Lock()
	defer q.Unlock()

	return q.closed
}

// ---------------------------------

func main() {
	var wg sync.WaitGroup
	q := NewQueue[int](3)

	for i := 0; i < 10; i++ {
		wg.Add(1)

		go func() {
			defer wg.Done()
			defer q.Close()
			println(q.IsClosed())
		}()
	}

	wg.Wait()
}

利用 nil 通道阻止退出。

func main() {
    <-(chan struct{})(nil)    // select{}
}

 

 

posted @   codestacklinuxer  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2023-05-11 gin 框架使用
2020-05-11 quic 2 ietf-transport-draft-ietf-quic-transport-09
2019-05-11 linux nf_conntrack 连接跟踪机制
2019-05-11 linux Netfilterr中扩展match target
2019-05-11 linux netfilter ----iptable_filter
2019-05-11 linux netfilter rule match target 数据结构
2019-05-11 linux netfilter 五个钩子点
点击右上角即可分享
微信分享提示