What is the simplest way to expand a slice to its capacity?

有些话、适合烂在心里 提交于 2020-08-27 04:15:15

问题


I have a program that uses a buffer pool to reduce allocations in a few performance-sensitive sections of the code.

Something like this: play link

// some file or any data source
var r io.Reader = bytes.NewReader([]byte{1,2,3})

// initialize slice to max expected capacity
dat := make([]byte, 20)

// read some data into it. Trim to length.
n, err := r.Read(dat)
handle(err)
dat = dat[:n]

// now I want to reuse it: 
for len(dat) < cap(dat) {
        dat = append(dat, 0) 
}

log.Println(len(dat))
// add it to free list for reuse later
// bufferPool.Put(dat)

I always allocate fixed length slices, which are guaranteed to be larger than the maximum size needed. I need to reduce size to the actual data length to use the buffer, but I also need it to be the maximum size again to read into it the next time I need it.

The only way I know of to expand a slice is with append, so that is what I am using. The loop feels super dirty though. And potentially inefficient. My benchmarks show it isn't horrible, but I feel like there has to be a better way.

I know only a bit about the internal representation of slices, but if I could only somehow override the length value without actually adding data, it would be really nice. I don't really need to zero it out or anything.

Is there a better way to accomplish this?


回答1:


"Extending" a slice to its capacity is simply a slice expression, and specify the capacity as the high index. The high index does not need to be less than the length. The restriction is:

For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length.

Example:

b := make([]byte, 10, 20)
fmt.Println(len(b), cap(b), b)

b = b[:cap(b)]
fmt.Println(len(b), cap(b), b)

Output (try it on the Go Playground):

10 20 [0 0 0 0 0 0 0 0 0 0]
20 20 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]



回答2:


You can expand a slice to its capacity with slicing:

s = s[:cap(s)]



回答3:


Using built-in copy & append func, many operations can be done on top of this.

See: https://github.com/golang/go/wiki/SliceTricks#expand



来源:https://stackoverflow.com/questions/46346077/what-is-the-simplest-way-to-expand-a-slice-to-its-capacity

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!