英文:
Truncate buffer from front
问题
bytes.Buffer
对象有一个Truncate(n int)
方法,用于丢弃除了前n
个字节之外的所有内容。
我需要的是完全相反的操作 - 保留最后n
个字节。
我可以这样做:
b := buf.Bytes()
buf.Reset()
buf.Write(b[len(b)-n:])
但我不确定这样做是否会高效地重用切片。
是否有更好的选择?
英文:
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?
答案1
得分: 1
有两种选择:
- 你提供的解决方案,允许重用前面的 'offset' 字节。
- 创建一个 bytes.NewBuffer(b[offset:]) 并使用它。这样做不会在你使用新缓冲区之前释放前面的 'offset' 字节,但可以避免复制的开销。
英文:
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.
答案2
得分: 0
让bytes.Buffer
处理缓冲区管理。内部的grow
方法会将数据向下滑动。使用Next
方法。例如,
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
// 保留最后n个字节。
if n > buf.Len() {
n = buf.Len()
}
buf.Next(buf.Len() - n)
fmt.Println(buf.Len(), buf.Bytes())
}
输出:
8 [0 1 2 3 4 5 6 7]
4 [4 5 6 7]
英文:
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]
答案3
得分: 0
我认为你的想法存在问题,因为“从开头截断缓冲区”是不可能的,因为内存分配器会分配完整的内存块,并且没有机制将已分配的块分割成一组“子块”,这实际上就是你所要求的。因此,为了支持“从开头截断”,bytes.Buffer
的实现将不得不分配一个较小的缓冲区,将“尾部”移动到那里,然后标记原始缓冲区以供重用。
这自然而然地引出了另一个想法:使用两个(或更多)缓冲区。它们可以分别分配,并且在你的算法中被视为相邻的,或者你可以使用自定义分配:先分配一个大的切片,然后将其切片两次或多次以产生几个物理上相邻的缓冲区,或者在其上滑动一个或多个“窗口”切片。当然,这意味着需要实现一个自定义的数据结构...
英文:
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…
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论