go 设计模式
2022年1月14日对象池
obj_pool.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package object_pool import ( "errors" "time" ) /** * 创建一个数据结构 */ type ReusableObj struct { } /** * 创建一个数据结构 */ type ObjPool struct { bufChan chan *ReusableObj //对象池 用于缓冲可重用对象 } /** * 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") } } /** * ObjPool 结构加入数据的方法 */ func (p *ObjPool) ReleaseObj(obj *ReusableObj) error { select { case p.bufChan <- obj: return nil default: return errors.New("overflow") } } func NewObjPool(numOfObj int) *ObjPool { objPool := ObjPool{} //创建一个ObjPool objPool.bufChan = make(chan *ReusableObj, numOfObj) //将 ReusableObj 添加到 objPool.bufChan for i := 0; i < numOfObj; i++ { objPool.bufChan <- &ReusableObj{} //传入空ReusableObj{} 到objPool.bufChan } return &objPool } |
obj_pool_test.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package object_pool import ( "fmt" "testing" "time" ) /** * 我也不是到这对象池有什么用 * 看这和循环的大转盘一样 */ func TestObjPool(t *testing.T) { pool := NewObjPool(10) //尝试放置超出池大小的对象 // if err := pool.ReleaseObj(&ReusableObj{}); err != nil { // t.Error(err) // } for i := 0; i < 11; i++ { //取出对象 if v, err := pool.GetObj(time.Nanosecond); err != nil { t.Error(err, "取出对象超时") } else { //打印取出的对象 fmt.Printf("%T\n", v) //将取出来的重置进去 if err := pool.ReleaseObj(v); err != nil { t.Error(err) } } } fmt.Println("Done") } |
sync pool对象缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package object_pool import ( "fmt" "runtime" "sync" "testing" ) func TestSyncPool(t *testing.T) { //创建一个对象池 pool := &sync.Pool{ //如果在对象没有找到对象,就会用这个方法创建一个新的对象 New: func() interface{} { fmt.Println("...在对象池创建一个新对象") return 100 }, } //.(int) 断言, 个人感觉就是预判 fmt.Println(pool.Get().(int)) pool.Put(1) //放入 pool.Put(2) //放入 pool.Put(3) //放入 pool.Put(4) //放入 fmt.Println(pool.Get().(int)) fmt.Println(pool.Get().(int)) fmt.Println(pool.Get().(int)) runtime.GC() //GC 会清除sync.pool中缓存的对象 fmt.Println(pool.Get().(int)) fmt.Println(pool.Get().(int)) fmt.Println(pool.Get().(int)) } func TestSyncPoolInMultiGroutine(t *testing.T) { pool := &sync.Pool{ New: func() interface{} { fmt.Println("Create a new object.") return 10 }, } pool.Put(100) pool.Put(99) pool.Put(98) var wg sync.WaitGroup //为了进程等待协程 for i := 0; i < 10; i++ { wg.Add(1) //添加一个等待运行不迷路 go func(id int) { fmt.Println(pool.Get()) //打印取出的数据 wg.Done() //告诉 wg.Wait 可以不用等待了 }(i) } wg.Wait() //运行等待 只有wg.Done通知后执行下面代码 } |