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

去切片覆盖

去切片覆盖

Go
皈依舞 2022-11-23 19:18:00
这是源代码:package mainfunc 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)    }}预期输出:123451123452实际输出:123452123452除⑤外,①~⑥的输出符合预期。但为什么⑤会slice3覆盖slice2?原因与指针或切片调整大小有关吗?
查看完整描述

1 回答

?
蝴蝶刀刀

TA贡献1801条经验 获得超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
  • 1 回答
  • 0 关注
  • 105 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号