对象池是经常会用到的一个功能,使用 buffer channel 实现
package obj_pool
import (
"errors"
"time"
)
type ReusableObj struct{}
type ObjPool struct {
bufChan chan *ReusableObj // 用于缓冲可重用对象
}
func NewObjPool(numOfObj int) *ObjPool {
ObjPool := ObjPool{}
ObjPool.bufChan = make(chan *ReusableObj, numOfObj) // numOfObj 表示迟的大小
for i := 0; i < numOfObj; i++ {
ObjPool.bufChan <- &ReusableObj{}
}
return &ObjPool
}
func (p *ObjPool) GetObj(timeout time.Duration) (*ReusableObj, error) {
select {
case ret := <-p.bufChan:
return ret, nil
case <-time.After(timeout): // 超时控制
return nil, errors.New("time out")
}
}
func (p *ObjPool) ReleaseObj(obj *ReusableObj) error {
select {
case p.bufChan <- obj:
return nil
default:
return errors.New("overflow")
}
}
下面是针对上面代码的测试程序
package obj_pool
import (
"fmt"
"testing"
"time"
)
func TestObjPool(t *testing.T) {
pool := NewObjPool(10)
// 测试 overflow
//if err := pool.ReleaseObj(&ReusableObj{}); err != nil{
// t.Error(err)
//}
for i := 0; i < 11; i++ {
if v, err := pool.GetObj(time.Second * 1); err != nil {
t.Error(err)
} else {
fmt.Printf("%T
", v)
if err := pool.ReleaseObj(v); err != nil {
t.Error(err)
}
}
}
fmt.Println("Done!")
}
对象池适用于复杂难于创建的对象,对于简单容易创建的对象不适用。