func (p *ChanPool) mergeState(state chanPoolState) {
	for state.avail > 0 || state.closed {
		select {
		case p.ch <- state:
			return
		case state1 := <-p.ch:
			state.avail += state1.avail
			state.closed = state.closed || state1.closed
		}
	}
}
mergeState updates the state in p.ch. Any available slots in state are added
to the existing slots.
package main
import (
	"sync"
)
type ChanPool struct {
	size int
	ch chan chanPoolState
	mu   sync.Mutex
	idle []*Conn
	closeCh chan struct{}
}
type chanPoolState struct {
	avail  int
	closed bool
}
func NewChanPool(size int) *ChanPool {
	p := &ChanPool{
		size:    size,
		ch:      make(chan chanPoolState, 1),
		closeCh: make(chan struct{}),
	}
	p.ch <- chanPoolState{avail: size}
	return p
}
func (p *ChanPool) Get() (*Conn, error) {
	var state chanPoolState
	select {
	case state = <-p.ch:
		if state.closed {
			return nil, ErrPoolClosed
		}
	case <-p.closeCh:
		return nil, ErrPoolClosed
	}
	state.avail--
	p.mu.Lock()
	if n := len(p.idle); n > 0 {
		c := p.idle[n-1]
		p.idle = p.idle[:n-1]
		p.mu.Unlock()
		p.mergeState(state)
		return c, nil
	}
	p.mu.Unlock()
	p.mergeState(state)
	c, err := Dial()
	if err != nil {
		p.mergeState(chanPoolState{avail: 1})
		return nil, err
	}
	return c, nil
}