sync pool 的 new函数

25 min read

在Go语言中,使用sync.Pool可以充分利用对象的复用,避免频繁地申请分配内存,以达到提升程序的性能的目的。

其中,sync.Pool的new函数是一个可选的函数类型,当不能从池中获取对象时,会调用该函数创建一个新的对象。其定义如下:

type Pool struct {
    // ...
    New func() interface{}
}

可以看出sync.Pool的new函数必须返回一个interface{}类型的对象,即一个新创建的对象,以便被放入池中等待复用。

当尝试从sync.Pool中获取对象时,若池中没有可用的对象,就会调用sync.Pool的New函数创建一个新的对象放入池中,这个过程可以理解为对象池的“初始化”。

示例代码如下:

package main

import (
	"fmt"
	"sync"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	pool := &sync.Pool{
		New: func() interface{} { // 当池为空时,调用该函数创建新实例
			return &Person{"Li Lei", 11} // 创建一个新对象
		},
	}

	// 从对象池中获取一个实例
	p1 := pool.Get().(*Person)
	fmt.Println(p1) // &{Li Lei 11}

	// 将实例放回对象池中
	pool.Put(p1)

	// 再从对象池中获取一个实例,此时已有对象,直接返回对象池中的实例,不再调用 New 函数
	p2 := pool.Get().(*Person)
	fmt.Println(p2) // &{Li Lei 11}
}

上述代码中,我们定义了一个sync.Pool类型的pool对象,并将其New函数定义为返回一个Person类型的实例指针。

在主函数中,我们首先通过sync.Pool对象的Get函数从池中获取一个对象,由于此时池中还没有可用的对象,因此会调用New函数创建一个新的对象,然后返回该对象的指针。接着,我们使用sync.Pool对象的Put函数将该对象放回池中,以便后续复用。

最后,我们再次使用sync.Pool对象的Get函数从池中获取一个对象,此时由于池中已经有了可用的对象,因此不需要再调用New函数,直接返回池中的对象即可。