写到Golang缓冲区的开头?

omg*_*mgj 5 go

我有:

var buffer bytes.Buffer
s := "something to do"
for i := 0; i < 10; i++ {
   buffer.WriteString(s)
}
Run Code Online (Sandbox Code Playgroud)

哪一个追加到缓冲区,是否可以写入缓冲区的开头?

小智 5

由于基础buf不是从导出的bytes.Buffer,因此您可以使用:

buffer.WriteString("B")
s := buffer.String()
buffer.Reset()
buffer.WriteString("A")
buffer.WriteString(s)
Run Code Online (Sandbox Code Playgroud)

试试这个The Go Playground

package main

import (
    "bytes"
    "fmt"
)

func main() {
    var buffer bytes.Buffer
    buffer.WriteString("B")
    s := buffer.String()
    buffer.Reset()
    buffer.WriteString("A" + s)
    fmt.Println(buffer.String())
}
Run Code Online (Sandbox Code Playgroud)

输出:

AB
Run Code Online (Sandbox Code Playgroud)


icz*_*cza 5

无法插入到开头,请参阅 Amd 的“解决方法”答案。要在开头覆盖内容,请继续阅读。

请注意,内部字节切片Buffer.buf未导出,但该方法Buffer.Bytes()返回一个与Buffer.buf内部切片共享相同后备数组的切片。

这意味着如果您bytes.Buffer通过调用创建一个新的Bytes.NewBuffer(),并在其重新切片为零长度并保留容量后传递此切片,您可以写入缓冲区的开头,覆盖第一个缓冲区的原始数据。

看这个例子:

buf := &bytes.Buffer{}
buf.WriteString("Hello  World")
fmt.Println("buf:", buf)

buf2 := bytes.NewBuffer(buf.Bytes()[:0])
buf2.WriteString("Gopher")
fmt.Println("buf:", buf)
fmt.Println("buf2:", buf2)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

buf: Hello  World
buf: Gopher World
buf2: Gopher
Run Code Online (Sandbox Code Playgroud)

注意:使用此技术,您还可以覆盖任意位置的内容,方法是使用所需的索引而不是重新0切片并传递切片。例如:

buf := &bytes.Buffer{}
buf.WriteString("Hello  World")
fmt.Println("buf:", buf)

buf2 := bytes.NewBuffer(buf.Bytes()[6:6]) // Start after the "Hello"
buf2.WriteString("Gopher")
fmt.Println("buf:", buf)
fmt.Println("buf2:", buf2)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

buf: Hello  World
buf: Hello Gopher
buf2: Gopher
Run Code Online (Sandbox Code Playgroud)

请注意,通过返回的切片对内容的“操作”Buffer.Bytes()可能只有在Buffer修改之前才能成功,之后有机会Buffer分配一个新的后备数组,并且您拥有的数组将被“分离”(以及对其进行进一步修改)不会反映在原文中Buffer):

切片仅在下一次缓冲区修改之前有效(即,仅在下一次调用 Read、Write、Reset 或 Truncate 等方法之前)。