Go 从前端截断缓冲区
Go 从前端截断缓冲区,go,Go,bytes.Buffer对象有一个Truncate(n int)方法来丢弃除第一个n字节以外的所有字节 我需要与之完全相反的结果-保留最后的n字节 我可以做到以下几点 b := buf.Bytes() buf.Reset() buf.Write(b[offset:]) 但我不确定这是否能有效地重复使用切片 有更好的选择吗?有两种选择: 您给出的解决方案允许重用第一个“偏移量”字节 创建一个bytes.NewBuffer(b[offset:]),并使用它。这将不允许在使用新缓冲区之前收集第一个
bytes.Buffer
对象有一个Truncate(n int)
方法来丢弃除第一个n
字节以外的所有字节
我需要与之完全相反的结果-保留最后的n
字节
我可以做到以下几点
b := buf.Bytes()
buf.Reset()
buf.Write(b[offset:])
但我不确定这是否能有效地重复使用切片
有更好的选择吗?有两种选择:
- 您给出的解决方案允许重用第一个“偏移量”字节
- 创建一个bytes.NewBuffer(b[offset:]),并使用它。这将不允许在使用新缓冲区之前收集第一个“偏移量”字节,但它避免了复制成本
- 让
字节。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
// Keep last n bytes.
if n > buf.Len() {
n = buf.Len()
}
buf.Next(buf.Len() - n)
fmt.Println(buf.Len(), buf.Bytes())
}
我认为你的想法的问题在于“从一开始就截断缓冲区”是不可能的,因为内存分配器将内存分配为完整的块,并且没有机器将已经分配的块分割成一组“子块”——本质上就是你所要求的。因此,为了支持“从头修剪”字节
的实现,Buffer
必须分配一个较小的缓冲区,将“尾部”移到那里,然后标记原始缓冲区以供重用
这自然会让我们想到另一个想法:使用两个(或更多)缓冲区。它们可能被单独分配,并被算法视为相邻的,或者您可能使用自定义分配:分配一个大片,然后将其重新切片两次或多次,以生成多个物理相邻的缓冲区,或者在其上滑动一个或多个“窗口”片。这意味着实现一个定制的数据结构,当然…接下来会调整片偏移量,但不会丢弃其他字节,如果在处理循环中执行,会导致大量内存消耗。
8 [0 1 2 3 4 5 6 7]
4 [4 5 6 7]