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{}
}
    http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号