--------------------------------------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() } }