猿问

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

我使用二维字节切片来表示一堆行,但是当我附加到其中一行时,我得到了一些非常奇怪的行为。


这是一个例子:


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


不负相思意
浏览 128回答 2
2回答

SMILET

底层存储是共享的,因此要获得所需的效果,您需要存储从 返回的切片的副本bytes.Split,而不仅仅是返回的切片。当您附加到返回的第一个切片时,您实际上是在踩到后面的切片。

慕斯709654

您正在做的是附加到字符串,而不是附加到数组,这会溢出切片的底层数据结构。这就是为什么数组的其余部分被您附加的字符串覆盖的原因。澄清(可能并非总是如此):该数组values由连续排列的 3 个 []byte 块组成。每个 []byte 块都有固定的长度(基于其中字符串的长度)。所以values[0]长度为 10(不包括 '\n' 或 '\0')。现在,如果您尝试附加"-inserted text-"到该块,字符将“流入”到连续块中values[1], 用 中的字符替换values[1]其中的字符"-inserted text-"。这就是为什么您会在values[1]和 中看到这些字符的一部分values[1]。
随时随地看视频慕课网APP

相关分类

Go
我要回答