附加到2d切片时的奇怪行为

时间:2016-05-17 16:22:01

标签: 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:")
    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

https://play.golang.org/p/iNw6s1S66U

为什么会发生这种情况,我该如何解决?

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

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

https://play.golang.org/p/pEflrhKLd4

2 个答案:

答案 0 :(得分:2)

底层存储是共享的,因此要获得所需的效果,您需要存储从bytes.Split返回的切片的副本,而不仅仅是返回的切片。当您追加到返回的第一个切片时,您基本上会在以下切片上踩踏。

答案 1 :(得分:1)

你正在做的是追加到字符串,而不是附加到数组,那就是溢出了切片的底层数据结构。这就是为什么数组的其余部分被你追加的字符串覆盖的原因。

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

数组values由连续排列的3 []字节块组成。每个[]字节块具有固定长度(基于其中的字符串长度)。因此values[0]的长度为10(不包括'\ n'或'\ 0')。现在,如果您尝试将"-inserted text-"附加到该块,则字符将“流”到连续的块values[1]中,将values[1]中的字符替换为"-inserted text-"中的字符}。这就是为什么你会在values[1]values[1]中看到这些字符的一部分。