I am using a 2D slice of bytes to represent a bunch of lines, but when I append to one of the lines, I get some very strange behavior.
Here is an example:
package main
import (
"bytes"
"fmt"
)
func main() {
str := []byte("first line
second line
third line")
values := bytes.Split(str, []byte("
"))
fmt.Println("Before:")
fmt.Println(string(values[0]))
fmt.Println(string(values[1]))
fmt.Println(string(values[2]))
fmt.Println()
values[0] = append(values[0], []byte("-inserted text-")...)
fmt.Println("After:")
fmt.Println(string(values[0]))
fmt.Println(string(values[1]))
fmt.Println(string(values[2]))
}
I would expect the output of this program to be
Before:
first line
second line
third line
After:
first line-inserted text-
second line
third line
But instead the output is:
Before:
first line
second line
third line
After:
first line-inserted text-
inserted te
t-ird line
https://play.golang.org/p/iNw6s1S66U
Why is this happening and how can I fix it?
Interestingly, this doesn't happen if I don't use split and instead define values like so:
values := [][]byte{[]byte("first line"), []byte("second line"), []byte("third line")}
The underlying storage is shared, so to get the effect you want, you would need to store copies of the slices returned from bytes.Split
, rather than just the slices returned. When you append to the first slice returned, you're essentially stomping all over the following slices.
What you're doing is appending to the string, instead of appending to the array and thats overflowing the underlying data structure for the slice. Which is why the rest of the array is overwritten with the string you're appending.
To clarify (this may not always be the case):
the array values
consists of 3 []byte blocks lined up consecutively. Each []byte block has a fixed length (based on the length of the string within it). So values[0]
has a length of 10 (excluding ' ' or '\0'). Now if you try to append "-inserted text-"
to that block, the characters will "flow" over into the consecutive block, values[1]
, replacing the characters within values[1]
with the characters in "-inserted text-"
. That's why you see parts of those characters within values[1]
and values[1]
.