为了账号安全,请及时绑定邮箱和手机立即绑定

去切片覆盖

去切片覆盖

Go
皈依舞 2022-11-23 19:18:00

这是源代码:


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?


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


查看完整描述

1 回答

?
蝴蝶刀刀

TA贡献1522条经验 获得超8个赞

在阅读我的答案的其余部分之前,请查看这个 SO 答案,以获得对切片实际是什么的真正有用的解释。通过打印出实际的切片标题可能更容易理解发生了什么。请参阅以下示例代码(并转到 playground):

package main


import (

    "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 个元素。


查看完整回答
反对 回复 2022-11-23

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信