Go创建对象池
使用Buffered Channel实现
//难以创建 可重用的对象 放置在对象池中
//
package obj_pool
import (
"fmt"
"testing"
"time"
)
func TestObjPool_GetObj(t *testing.T) {
pool := NewObjPool(10)
// if err := pool.ReleaseObj(&ReusableObjP{});
//err ! = nil{
//t .Error(err)
//} 尝试放置超出池数量的数组 发出overflow状态
for i := 0; i < 15; i++ {
if v, err := pool.GetObj(time.Second * 1); err != nil {
t.Error(err)
} else {
fmt.Printf("%d,%T\n", i, v)
if err := pool.ReleaseObj(v); err != nil {
t.Error(err)
//拿不到对象所以出现了Timeout的现象
}
}
//fmt.Println("Done")
}
//如何做一个 符合各种类型的池 使用空接口+类型断言
}
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)
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 ")
// 超时 高可用的净距
//高可用slow response 和 比quick 费里尔 更快的case
}
}
func (p *ObjPool)ReleaseObj(obj * ReusableObj) error {
//为了防治对象太多 塞不进来阻塞
select {
case p.bufChan <- obj:
return nil
default:
return errors.New("overflow")
}
}
特点
使用Buffered Channel缓存难以创建,可复用的对象,不一定会提高程序性能,锁和为了保护线程安全的同步机制的影响。
对象简单,易于创建,要用性能测试权衡,评估是否这种方式真的给性能带来了优化。