Go 附加到二维切片时的奇怪行为

Go 附加到二维切片时的奇怪行为,go,slice,Go,Slice,我使用一个2D字节片来表示一组行,但是当我附加到其中一行时,我得到了一些非常奇怪的行为 以下是一个例子: package main import ( "bytes" "fmt" ) func main() { str := []byte("first line\nsecond line\nthird line") values := bytes.Split(str, []byte("\n")) fmt.Println("Before:") f

我使用一个2D字节片来表示一组行,但是当我附加到其中一行时,我得到了一些非常奇怪的行为

以下是一个例子:

package main

import (
    "bytes"
    "fmt"
)

func main() {
    str := []byte("first line\nsecond line\nthird line")
    values := bytes.Split(str, []byte("\n"))

    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]))
}
我希望这个程序的输出是

Before:
first line
second line
third line

After:
first line-inserted text-
second line
third line
但结果是:

Before:
first line
second line
third line

After:
first line-inserted text-
inserted te
t-ird line

为什么会发生这种情况?我如何修复它

有趣的是,如果我不使用split,而是这样定义值,则不会发生这种情况:

values := [][]byte{[]byte("first line"), []byte("second line"), []byte("third line")}

您所做的是追加到字符串,而不是追加到数组,这会溢出切片的底层数据结构。这就是为什么数组的其余部分会被附加的字符串覆盖

澄清(情况可能并非总是如此):


数组
由连续排列的3[]字节块组成。每个[]字节块都有固定的长度(基于其中字符串的长度)。因此
值[0]
的长度为10(不包括“\n”或“\0”)。现在,如果您尝试将
“-inserted text-”
附加到该块,字符将“流动”到连续块
values[1]
,将
values[1]
中的字符替换为
“-inserted text-”
中的字符。这就是为什么在
values[1]
values[1]
中可以看到这些字符的一部分,底层存储是共享的,因此为了获得想要的效果,您需要存储从
bytes.Split返回的片的副本,而不仅仅是返回的片。当您附加到返回的第一个切片时,实际上是在对下面的切片进行踩踏。

当您说存储是共享的时,您的意思是什么?您指的是连续排列的片的元素吗?valriable
str
是一个字节片,具有一定量的后端存储。然后
byte.Slice
返回一个[]字节的片,所有字节都指向同一后备存储器。所以它们(最初)都指向同一个共享存储。对。我能够证实这一点。