Write to beginning of the buffer in Golang?

huangapple go评论71阅读模式
英文:

Write to beginning of the buffer in Golang?

问题

我有:

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

这段代码将字符串追加到缓冲区中,是否可能向缓冲区的开头写入数据?

英文:

I have:

var buffer bytes.Buffer
s := &quot;something to do&quot;
for i := 0; i &lt; 10; i++ {
   buffer.WriteString(s)
}

Which appends to the buffer, is it possible to write to the beginning of a buffer?

答案1

得分: 6

由于bytes.Buffer中的buf底层不可导出,您可以使用以下方法:

buffer.WriteString("B")
s := buffer.String()
buffer.Reset()
buffer.WriteString("A")
buffer.WriteString(s)

您可以在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())
}

输出结果为:

AB
英文:

Since the underlying buf not exported from bytes.Buffer, you may use:

buffer.WriteString(&quot;B&quot;)
s := buffer.String()
buffer.Reset()
buffer.WriteString(&quot;A&quot;)
buffer.WriteString(s)

Try this The Go Playground:

package main

import (
	&quot;bytes&quot;
	&quot;fmt&quot;
)

func main() {
	var buffer bytes.Buffer
	buffer.WriteString(&quot;B&quot;)
	s := buffer.String()
	buffer.Reset()
	buffer.WriteString(&quot;A&quot; + s)
	fmt.Println(buffer.String())
}

output:

AB

答案2

得分: 6

在开头插入是不可能的,参考Amd的答案找到一个“变通方法”。如果要覆盖开头的内容,请继续阅读。

请注意,内部的字节切片Buffer.buf是不可导出的,但是方法Buffer.Bytes()返回一个切片,与Buffer.buf内部切片共享相同的底层数组。

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

看下面的例子:

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)

输出结果(在Go Playground上尝试):

buf: Hello  World
buf: Gopher World
buf2: Gopher

注意:使用这种技术,你还可以通过使用所需索引进行重新切片而不是0来覆盖任意位置的内容,并传递该切片。例如:

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

buf2 := bytes.NewBuffer(buf.Bytes()[6:6]) // 从“Hello”之后开始
buf2.WriteString("Gopher")
fmt.Println("buf:", buf)
fmt.Println("buf2:", buf2)

输出结果(在Go Playground上尝试):

buf: Hello  World
buf: Hello Gopher
buf2: Gopher

请注意,通过Buffer.Bytes()返回的切片对内容的“操作”只能在Buffer被修改之前成功,之后Buffer有可能分配一个新的底层数组,你所拥有的那个切片将会“分离”(因此对它的进一步修改将不会反映在原始的Buffer中):

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

英文:

Inserting to the beginning is not possible, see Amd's answer for a "workaround". For overwriting content at the beginning, read on.

Note that the internal byte slice Buffer.buf is not exported, but the method Buffer.Bytes() returns a slice sharing the same backing array as the Buffer.buf internal slice.

This means if you create a new bytes.Buffer by calling Bytes.NewBuffer(), and pass this slice after reslicing it to zero length and capacity retained, you can write to the beginning of the buffer, overwriting original data of the first buffer.

See this example:

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

buf2 := bytes.NewBuffer(buf.Bytes()[:0])
buf2.WriteString(&quot;Gopher&quot;)
fmt.Println(&quot;buf:&quot;, buf)
fmt.Println(&quot;buf2:&quot;, buf2)

Output (try it on the Go Playground):

buf: Hello  World
buf: Gopher World
buf2: Gopher

Note: Using this technique, you can also overwrite content at arbitrary position, by reslicing using the desired index instead of 0 and passing the slice. For example:

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

buf2 := bytes.NewBuffer(buf.Bytes()[6:6]) // Start after the &quot;Hello&quot;
buf2.WriteString(&quot;Gopher&quot;)
fmt.Println(&quot;buf:&quot;, buf)
fmt.Println(&quot;buf2:&quot;, buf2)

Output (try it on the Go Playground):

buf: Hello  World
buf: Hello Gopher
buf2: Gopher

Note that the "manipulation" of the content through the slice returned by Buffer.Bytes() may only succeed until the Buffer is modified, after that there's a chance that Buffer allocates a new backing array and the one you have will be "detached" (and so further modification on it will not be reflected in the original Buffer):

> The slice is valid for use only until the next buffer modification (that is, only until the next call to a method like Read, Write, Reset, or Truncate).

huangapple
  • 本文由 发表于 2016年10月25日 13:07:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/40231761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定