The bytes.Buffer
object has a Truncate(n int)
method to discard all but the first n
bytes.
I'd need the exact inverse of that - keeping the last n
bytes.
I could do the following
b := buf.Bytes()
buf.Reset()
buf.Write(b[offset:])
but I'm not sure if this will re-use the slice efficiently.
Are there better options?
There are two alternatives:
Let bytes.Buffer
handle the buffer management. The internal grow
method slides the data down. Use the Next
method. For example,
package main
import (
"bytes"
"fmt"
)
func main() {
var buf bytes.Buffer
for i := 0; i < 8; i++ {
buf.WriteByte(byte(i))
}
fmt.Println(buf.Len(), buf.Bytes())
n := buf.Len() / 2
// Keep last n bytes.
if n > buf.Len() {
n = buf.Len()
}
buf.Next(buf.Len() - n)
fmt.Println(buf.Len(), buf.Bytes())
}
Output:
8 [0 1 2 3 4 5 6 7]
4 [4 5 6 7]
I reckon the problem with your idea is that "truncating the buffer from its start" is impossible simply because the memory allocator allocates memory in full chunks and there's no machinery in it to split an already allocated chunk into a set of "sub chunks" — essentially what you're asking for. So to support "trimming from the beginning" the implementation of bytes.Buffer
would have to allocate a smaller buffer, move the "tail" there and then mark the original buffer for reuse.
This naturally leads us to another idea: use two (or more) buffers. They might either be allocated separately and treated as adjacent by your algorythms or you might use custom allocation: allocate one big slice and then reslice it twice or more times to produce several physically adjacent buffers, or slide one or more "window" slices over it. This means implementing a custom data structure of course…