--------------------------------------pool.go----------------------------------------------
package pool import ( "sync" "io" "errors" "log" ) var ( ErrSizeTooSmall = errors.New("池大小必须为正整数") ErrPoolClosed = errors.New("池已关闭") ) //Pool 管理一组可以安全地在多个goroutine间共享的资源,被管理资源必须实现io.Closer接口 type Pool struct { m sync.Mutex resources chan io.Closer factory func() (io.Closer, error) closed bool } //New 创建一个新池,并限定池大小,并需要一个创建资源的工厂函数 func New(size int, factory func() (io.Closer, error)) (*Pool, error) { if size < 1 { return nil, ErrSizeTooSmall } return &Pool{ factory: factory, resources: make(chan io.Closer, size), closed: false, }, nil } //Acquire 从池中获取一个资源 func (p *Pool) Acquire() (io.Closer, error) { select { // 检查池中是否有空闲资源,如果不ok,则说明池已关闭 case r, ok := <-p.resources: log.Println("Acquire:", "Shared Resource") if !ok { return nil, ErrPoolClosed } return r, nil // 池中取不到的时候,新建一个 default: log.Println("Acquired", "New Resource") return p.factory() } } // Release 将一个使用完的资源放回池里 func (p *Pool) Release(r io.Closer) { // 保证本操作和Release操作的安全 p.m.Lock() defer p.m.Unlock() // 如果池已关闭,销毁资源 if p.closed { r.Close() return } select { // 尝试将资源放回队列 case p.resources <- r: log.Println("Releaser:", "In Queue") // 如果队列已满,关闭这个资源 default: log.Println("Release:", "Closing") r.Close() } } // Close 关闭池,并关闭池的所有资源 func (p *Pool) Close() { // 保证本操作与Release操作的安全 p.m.Lock() defer p.m.Unlock() // pool已关闭,什么也不做 if p.closed { return } // 标记池已关闭 p.closed = true // 清空chan之前需要先关闭,否则会发生死锁 close(p.resources) // 关闭资源 for r := range p.resources { r.Close() } }