omgj
omgj

Reputation: 1379

Write to beginning of the buffer in Golang?

I have:

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

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

Upvotes: 7

Views: 12644

Answers (2)

icza
icza

Reputation: 417692

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 := &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)

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 := &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)

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).

Upvotes: 6

user6169399
user6169399

Reputation:

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

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

Try this 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())
}

output:

AB

Upvotes: 8

Related Questions