有没有办法在 Go中分配一个未初始化的切片?一种常见的模式是创建一个给定大小的切片作为缓冲区,然后只使用它的一部分来接收数据。例如:
b := make([]byte, 0x20000) // b is zero initialized
n, err := conn.Read(b)
// do stuff with b[:n]. all of b is zeroed for no reason
当分配大量缓冲区时,此初始化可能会累加,因为规范声明它将默认在分配时初始化数组。
您可以从bufs.Cache.Get获取非零字节缓冲区(或查看并发安全版本)。从文档:CCache
注意:Get 返回的缓冲区不保证归零。例如,将缓冲区传递给 io.Reader 是可以的。如果您需要一个归零缓冲区,请使用 Cget。
从技术上讲,您可以通过在 go 运行时之外分配内存并使用unsafe.Pointer
,但这绝对是错误的做法。
更好的解决方案是减少分配次数。将缓冲区移到循环之外,或者,如果您需要每个 goroutine 缓冲区,则在池中分配其中几个,仅在需要时分配更多。
type BufferPool struct {
Capacity int
buffersize int
buffers []byte
lock sync.Mutex
}
func NewBufferPool(buffersize int, cap int) {
ret := new(BufferPool)
ret.Capacity = cap
ret.buffersize = buffersize
return ret
}
func (b *BufferPool) Alloc() []byte {
b.lock.Lock()
defer b.lock.Unlock()
if len(b.buffers) == 0 {
return make([]byte, b.buffersize)
} else {
ret := b.buffers[len(b.buffers) - 1]
b.buffers = b.buffers[0:len(b.buffers) - 1]
return ret
}
}
func (b *BufferPool) Free(buf []byte) {
if len(buf) != b.buffersize {
panic("illegal free")
}
b.lock.Lock()
defer b.lock.Unlock()
if len(b.buffers) < b.Capacity {
b.buffers = append(b.buffers, buf)
}
}