Golang 切片与函数参数 "陷阱"

本文详细探讨了Golang中切片的工作原理,包括切片的创建、复制、追加以及作为函数参数时的行为。重点阐述了切片如何共享底层数组,以及在超出容量时的动态扩容机制。通过实例展示了函数参数传递切片时,实际上是传值而非传引用,但因共享底层数组,导致函数内部的修改会影响到原始切片。同时,利用指针可以实现对原始切片的直接修改。
摘要由CSDN通过智能技术生成

slice 基本实现

   Golang中的slice,是一个看似array却不是array的复合结构。切片顾名思义,就是数组切下来的一个片段。slice结构大致存储了三个部分,第一部分为指向底层数组的指针ptr,其次就是切片的大小len和切片的容量cap:

    

   有一个数组arr是一个包含五个int类型的结构,它的切片slice只是从其中取了1到3这几个数字。我们同样可以在生成一个切片 slice2 := arr[2:5], 所取的就是数组后面的连续块。它们共同使用arr作为底层的结构,可以看见公用了数字的第3,4个元素。修改其中任何一个,都能改变两个切片的值。

func main() {

    arr := [5]int{0, 1, 2, 3, 4}
    fmt.Println(arr)

    slice := arr[1:4]
    slice2 := arr[2:5]

    fmt.Printf("arr %v, slice1 %v, slice2 %v, %p %p %p\n", arr, slice, slice2, &arr, &slice, &slice2)

    fmt.Printf("arr[2]%p slice[1] %p slice2[0]%p\n", &arr[2], &slice[1], &slice2[0])

    arr[2] = 2222

    fmt.Printf("arr %v, slice1 %v, slice2 %v\n", arr, slice, slice2)


    slice[1] = 1111

    fmt.Printf("arr %v, slice1 %v, slice2 %v\n", arr, slice, slice2)

}

   输出的值为:

[0 1 2 3 4]
arr [0 1 2 3 4], slice1 [1 2 3], slice2 [2 3 4], 0xc42006e0c0 0xc4200660c0 0xc4200660e0
arr[2]0xc42006e0d0 slice[1] 0xc42006e0d0 slice2[0]0xc42006e0d0
arr [0 1 2222 3 4], slice1 [1 2222 3], slice2 [2222 3 4]
arr [0 1 1111 3 4], slice1 [1 1111 3], slice2 [1111 3 4]

  由此可见,数组的切片,只是从数组上切一段数据下来,不同的切片,其实是共享这些底层的数据。不过这些本身是不一样的对象,其内存地址都不一样。

  从数组中切下来形成切片很好理解,有时候我们用make函数创建切片,实际上golang会在底层创建一个匿名的数组。如果从新的slice再切,那么新创建的两个切片都共享这个底层的匿名数组。

func main() {

    slice := make([]int, 5)
    for i:=0; i<len(slice);i++{
        slice[i] = i
    }
    fmt.Printf("slice %v \n", slice)

    slice2 := slice[1:4]
    fmt.Printf("slice %v, slice2 %v \n", slice, slice2)

    slice[1] = 1111
    fmt.Printf("slice %v, slice2 %v \n", slice, slice2)
}

   输出如下:

slice [0 1 2 3 4] 
slice [0 1 2 3 4], slice2 [1 2 3] 
slice [0 1111 2 3 4], slice2 [1111 2 3]

 

slice的复制

 

   既然slice的创建依赖于数组,有时候新生成的slice会修改,但又不想修改原来的切片或数组。此时就需要针对原来的切片进行复制了。

func main() {

    slice := []int{0, 1, 2, 3, 4}

    slice2 := slice[1:4]

    slice3 :=
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值