切片底層陣列詳解

輕描淡寫 發表於 2021-09-19
package main

import "fmt"

func main() {
    s := []int{0,1,2,3,4,5,6,7,8,9}
    s1 := s[1:5]
    fmt.Printf("s[1] ==> %p,s長度==> %d,s容量==>%d \n",&s[1],len(s),cap(s))
    fmt.Printf("s[2] ==> %p \n",&s[2])
    fmt.Printf("s[3] ==> %p \n",&s[3])
    fmt.Printf("s[4] ==> %p \n",&s[4])
    fmt.Printf("s[5] ==> %p \n",&s[5])
    fmt.Printf("s[6] ==> %p \n",&s[9])
    fmt.Println("--------------------------------------")
    fmt.Printf("s1[0] ==> %p ,s1長度==> %d,s1容量==>%d \n",&s1[0],len(s1),cap(s1))
    fmt.Printf("s1[1] ==> %p \n",&s1[1])
    fmt.Printf("s1[2] ==> %p \n",&s1[2])
    fmt.Printf("s1[3] ==> %p \n",&s1[3])
    fmt.Println("--------------------------------------")
    s2 := append(s1,10)
    fmt.Printf("s2[0] ==> %p s2長度==> %d,s2容量==>%d \n",&s2[0],len(s2),cap(s2))
    fmt.Printf("s2[4] ==> %p \n",&s2[4])
    fmt.Println("--------------------------------------")
    s3 := append(s2,[]int{11,12,13,14,15}...)
    fmt.Printf("s3[0] == > %p s3長度==> %d,s3容量==>%d \n",&s3[0],len(s3),cap(s3))
    fmt.Println(s3)
}
s[1] ==> 0xc000014198,s長度==> 10,s容量==>10
s[2] ==> 0xc0000141a0
s[3] ==> 0xc0000141a8
s[4] ==> 0xc0000141b0
s[5] ==> 0xc0000141b8
s[6] ==> 0xc0000141d8
--------------------------------------
s1[0] ==> 0xc000014198 ,s1長度==> 4,s1容量==>9
s1[1] ==> 0xc0000141a0
s1[2] ==> 0xc0000141a8
s1[3] ==> 0xc0000141b0
--------------------------------------
s2[0] ==> 0xc000014198 s2長度==> 5,s2容量==>9
s2[4] ==> 0xc0000141b8
--------------------------------------
s3[0] == > 0xc000016090 s3長度==> 10,s3容量==>18
[1 2 3 4 10 11 12 13 14 15]

1.s1 := s[1:5],這是s1的長度為 4 ,容量就是 s從 1 開始後面的容量,當我們列印 s1s的前幾個元素指標的時候發現s1的四個元素的指標正好是s的 第一號到第四號,可以證明 s1s公用一個底層陣列。

2.這時候我們往s1裡新增一個元素,再列印元素的指標,發現s2的第四號元素地址正好和 s1的第五號元素地址相同,這證明s2和前兩個切片還是共用底層陣列。

3.我們往s2新增五個元素,s2本來的長度是 5 ,容量是 9 ,這時候新增五個元素會導致自動擴容,這時候再列印s3的元素地址,發現與前三個切片的元素地址不同,說明擴容後已經重新分配了記憶體地址。自動擴容的容量計算在上一篇。

本作品採用《CC 協議》,轉載必須註明作者和本文連結