提前注意:

sync.Poolsync.Pool

存储在池中的任何项目 都可能随时自动删除,恕不另行通知 。如果在发生这种情况时 Pool 拥有唯一的引用,则该项目可能会被释放。

Pool
sync.Pool

最简单的内存池“实现”是缓冲通道。

defer

让我们使用它作为我们的大对象的类型:

type BigObject struct {
    Id        int
    Something string
}

创建池是:

pool := make(chan *BigObject, 10)

池的大小就是通道缓冲区的大小。

用昂贵对象的指针填充池(这是可选的,请参阅末尾的注释):

for i := 0; i < cap(pool); i++ {
    bo := &BigObject{Id: i}
    pool <- bo
}

许多 goroutine 使用池:

wg := sync.WaitGroup{}
for i := 0; i < 100; i++ {
    wg.Add(1)
    go func() {
        defer wg.Done()
        bo := <-pool
        defer func() { pool <- bo }()
        fmt.Println("Using", bo.Id)
        fmt.Println("Releasing", bo.Id)
    }()
}

wg.Wait()

在Go Playground上尝试一下。

select
var bo *BigObject
select {
case bo = <-pool: // Try to get one from the pool
default: // All in use, create a new, temporary:
    bo = &BigObject{Id:-1}
}
select
select {
case pool <- bo: // Try to put back into the pool
default: // Pool is full, will be garbage collected
}

笔记:

select

您必须确保您没有在请求之间泄漏信息,例如,确保您不使用已设置并属于其他请求的共享对象中的字段和值。