sync.Pool 用于存储临时对象,它将使用完毕的对象存入对象池中,在需要的时候取出来重复使用,目的是为了避免重复创建相同的对象造成 GC 负担过重。从 Pool 中取出对象时,如果 Pool 中没有对象,将返回 nil,但是如果给 Pool.New 字段指定了一个函数的话,Pool 将使用该函数创建一个新对象返回。

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. func main() {
  7. sp := sync.Pool{
  8. //创建一个Pool,并且实现New()函数
  9. New: func() interface{}{
  10. return "hello world"
  11. },
  12. }
  13. // 第1次获取池中值
  14. v1 := sp.Get()
  15. fmt.Println("第1次值:", v1)
  16. //New()返回的是interface{}通过类型断言来转换
  17. if v1,ok := v1.(string);ok {
  18. v1= "hello golang"
  19. sp.Put(v1) // 获取池子中元素 然后修改值
  20. }
  21. // 第2次获取池中值
  22. v2 := sp.Get()
  23. fmt.Println("第2次值:", v2)
  24. // 第3次获取池中值
  25. v3 := sp.Get()
  26. //因为池中的对象已经没有了,所以又重新通过New()创建一个新对象,放入池中,然后返回
  27. fmt.Println("第3次值:", v3)
  28. }

打印结果

  1. 1次值: hello world
  2. 2次值: hello golang
  3. 3次值: hello world

尝试从私有对象获取
私有对象不存在,尝试从当前Processor的共享池获取
如果当前Processor共享池是空的,那么就尝试去其他Processor的共享池获取
如果所有子池都是空的,最后就用指定的New 函数产生一个新的对象返回。

放回

如果私有对象不存在则保存为私有对象
如果私有对象存在,放入当前Processor子池的共享池

生命周期

GC会清除sync.pool缓存的对象
对象的缓存有效期为下一次GC之前

  1. func TestSyncPool(t *testing.T) {
  2. pool := &sync.Pool{New: func() interface{} {
  3. return 2
  4. }}
  5. a, ok := pool.Get().(int)
  6. if ok {
  7. fmt.Println(a)
  8. }
  9. pool.Put(3)
  10. b, ok := pool.Get().(int)
  11. if ok {
  12. fmt.Println(b)
  13. }
  14. }

使用

适用与通过复用,降低复杂对象的创建和GC代价
协程安全,会有锁的开销
生命周期受GC影响,不适用于连接池等,需要自己管理生命周期的资源的池化