去切片覆盖

这是源代码:


package main


func main() {

    testSlice()

}


func testSlice() {

    slice := make([]int, 0)

    //slice = append(slice, 1)  ①

    //slice = append(slice, 1, 2)  ②

    //slice = append(slice, 1, 2, 3)  ③

    //slice = append(slice, 1, 2, 3, 4)  ④

    slice = append(slice, 1, 2, 3, 4, 5)  ⑤

    //slice = append(slice, 1, 2, 3, 4, 5, 6)  ⑥


    slice2 := append(slice, 1)

    slice3 := append(slice, 2)


    for _, i := range slice2 {

        print(i)

    }

    println()

    for _, i := range slice3 {

        print(i)

    }

}

预期输出:


123451

123452

实际输出:


123452

123452

除⑤外,①~⑥的输出符合预期。但为什么⑤会slice3覆盖slice2?


原因与指针或切片调整大小有关吗?


皈依舞
浏览 106回答 1
1回答

蝴蝶刀刀

在阅读我的答案的其余部分之前,请查看这个 SO 答案,以获得对切片实际是什么的真正有用的解释。通过打印出实际的切片标题可能更容易理解发生了什么。请参阅以下示例代码(并转到 playground):package mainimport (    "fmt"    "reflect"    "unsafe")func main() {    testSlice()}func testSlice() {    slice := make([]int, 0)    slice = append(slice, 1, 2, 3, 4, 5)    fmt.Printf("%+v\n", (*reflect.SliceHeader)(unsafe.Pointer(&slice)))    slice2 := append(slice, 1)    fmt.Printf("%+v\n", (*reflect.SliceHeader)(unsafe.Pointer(&slice2)))    slice3 := append(slice, 2)    fmt.Printf("%+v\n", (*reflect.SliceHeader)(unsafe.Pointer(&slice3)))    for _, i := range slice2 {        print(i)    }    println()    for _, i := range slice3 {        print(i)    }}这将打印如下内容:&{Data:824634441776 Len:5 Cap:6}&{Data:824634441776 Len:6 Cap:6}&{Data:824634441776 Len:6 Cap:6}这表明所有变量slice、slice2和slice3都指向相同的数据(Data这是指向切片第一个元素的指针)但切片标头本身不同。当您执行appends 时,您正在修改所有变量共享的基础切片,并将新的切片标头存储到新变量中。slice2和的切片标头slice3正在查看相同的数据切片,因此当您出现并执行追加时slice3,您将覆盖所有变量共享的基础切片中的第 6 个元素。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go