从前面截断缓冲区

时间:2013-12-08 16:49:22

标签: go

bytes.Buffer对象使用Truncate(n int)方法丢弃除第一个n字节以外的所有字符。

我需要与此完全相反 - 保持最后 n字节。

我可以做以下

b := buf.Bytes()
buf.Reset()
buf.Write(b[offset:])

但我不确定这是否会有效地重复使用切片。

有更好的选择吗?

3 个答案:

答案 0 :(得分:2)

有两种选择:

  • 您提供的解决方案,允许第一个'偏移'要重用的字节。
  • 创建一个bytes.NewBuffer(b [offset:])并使用它。这将不允许第一个'偏移'在您使用新缓冲区完成之前要收集的字节数,但它可以避免复制成本。

答案 1 :(得分: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

    // Keep last n bytes.
    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]

答案 2 :(得分:0)

我认为你的想法的问题是“从开始就截断缓冲区”是不可能的,因为内存分配器在完整的块中分配内存它没有机器来分割已经分配的大块进入一组“子块” - 基本上就是你所要求的。因此,为了支持“从头开始修剪”,bytes.Buffer的实现必须分配一个较小的缓冲区,在那里移动“尾部”,然后标记原始缓冲区以便重用。

这自然会引出另一个想法:使用两个(或更多)缓冲区。它们可以单独分配并且处理作为您的algorythms相邻,或者您可以使用自定义分配:分配一个大切片然后重新切片两次或更多次以生成几个物理上相邻的缓冲区,或者滑动一个或者更多“窗口”切片。这意味着当然要实现自定义数据结构......