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]