从前面截断缓冲区

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:

  • The solution you give, which allows the first 'offset' bytes to be reused.
  • Create a bytes.NewBuffer(b[offset:]) and use that. This will not allow the first 'offset' bytes to be collected until you're done with the new buffer, but it avoids the cost of copying.

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…