分配未初始化的切片

Is there some way to allocate an uninitialized slice in Go? A frequent pattern is to create a slice of a given size as a buffer, and then only use part of it to receive data. For example:

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

This initialization can add up when lots of buffers are being allocated, as the spec states it will default initialize the array on allocation.

Technically you could by allocating the memory outside the go runtime and using unsafe.Pointer, but this is definitely the wrong thing to do.

A better solution is to reduce the number of allocations. Move buffers outside loops, or, if you need per goroutine buffers, allocate several of them in a pool and only allocate more when they're needed.

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)
    }
}

You can get non zeroed byte buffers from bufs.Cache.Get (or see CCache for the concurrent safe version). From the docs:

NOTE: The buffer returned by Get is not guaranteed to be zeroed. That's okay for e.g. passing a buffer to io.Reader. If you need a zeroed buffer use Cget.