go 语言 buffer.truncate 分析

对于Golang的初学者,Truncate方法的行为使人迷惑,它不是从 buffer的头部截取 n 个字节,而是丢弃除了前n个未读取的字节之外的所有未读取的字节,也是就只保留已读取的字节和还没有读取的前n个字节。这种逻辑确实让人不太适应

// Truncate discards all but the first n unread bytes from the buffer
// but continues to use the same allocated storage.
// It panics if n is negative or greater than the length of the buffer.
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		b.Reset()
		return
	}
	b.lastRead = opInvalid
	if n < 0 || n > b.Len() {
		panic("bytes.Buffer: truncation out of range")
	}
	b.buf = b.buf[:b.off+n]
}

从源码的注释中还可以看到,截取后使用原 buffer保存保留下来的节字,不再额外占用内存空间。同时 n 的大小不能超过未读取字节的长度(第10行)

func truncate() {
  var buffer bytes.Buffer
  str := "Simple byte buffer for marshaling data."
  buffer.WriteString(str)
  p := make([]byte, 8)
  buffer.Read(p) // Simple b
  fmt.Println(string(p))

  buffer.Truncate(10)    // 截断到前10个未读节字 Simple byte buffer
  buffer.Read(p)         // 读取8个字节
  fmt.Println(string(p)) // yte buff
}
  • p := make([]byte, 8)先读取了8个字节
  • buffer.Truncate(10) 再从没有读取的字节中取出10个,丢掉其余未读取的字节,把已读取的8个字节和取出的10个字节保存到 buffer中,此时buffer中的内容为Simple byte buffer
  • buffer.Read(p) 再读取8个字节,注意:这里不是从 buffer 的头部读取,而是从未读取处开始读取,即从y开始读取