Go 知识点(15)— 切片长度和容量
生活随笔
收集整理的這篇文章主要介紹了
Go 知识点(15)— 切片长度和容量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 切片聲明時默認的長度和容量
1.1 切片聲明時不指定容量
切片在使用 make 聲明時,如果沒有顯式的說明切片的容量,那么默認容量和切片的長度保持一致。
func main() {s1 := make([]int, 3)fmt.Println("s1 length: ", len(s1)) // s1 length: 3fmt.Println("s1 capacity: ", cap(s1)) // s1 capacity: 3fmt.Printf("s1 value: %#v\n", s1) // s1 value: []int{0, 0, 0}
}
由上面可以看出來,當只聲明切片的長度時,容量是和長度保持一致的。
1.2 切片聲明時指定容量
而在聲明切片時,如果指定切片的容量,那么容量就為指定的值
func main() {s2 := make([]int, 3, 7)fmt.Println("s2 length: ", len(s2)) // s2 length: 3fmt.Println("s2 capacity: ", cap(s2)) // s2 capacity: 7fmt.Printf("s2 value: %#v\n", s2) // s2 value: []int{0, 0, 0}
}
2. 指定切片區間作為新切片時,新切片的長度和容量
看下面代碼
func main() {s3 := []int{1, 2, 3, 4, 5, 6, 7, 8}s4 := s3[3:6]fmt.Printf("s4 length is: %d\n", len(s4)) // s4 length is: 3fmt.Printf("s4 capacity is: %d\n", cap(s4)) // s4 capacity is: 5fmt.Printf("s4 value is: %d\n", s4) // s4 value is: [4 5 6]s5 := s4[:cap(s4)]fmt.Printf("s5 length is: %d\n", len(s5)) // s5 length is: 5fmt.Printf("s5 capacity is: %d\n", cap(s5)) // s5 capacity is: 5fmt.Printf("s5 value is: %d\n", s5) // s5 value is: [4 5 6 7 8]
}
切片 s4 是在切片 s3 的基礎上通過索引劃分出來一個新的切片,所以切片 s4 的長度是 6-3=3,而切片 s4 的容量 cap(s4)=8-3=5 ,其中 8 為切片 s3 的長度,3 為切片s4 在s3 的起始位置。
cap(s4)=5,所以 s4[:cap(s4)] 就等于 s4[:5] 由于 s4 和 s3 共用同一個數組,所以 s4[:5] 就相當于從 s4 起始的位置開始到第 5 個元素,也就是從 s3 的第三個元素開始一直到第 3 + 5 = 8 個元素,所以 s5=[4 5 6 7 8] 。
3. 切片擴容時容量的變化
切片通過 append 擴容時,如果切片長度小于當前的容量,那么切片不會擴容,如果追加元素后切片長度大于當前的容量時,切片就會擴容,擴容機制如下:
- 當擴容之后的元素長度小于
1024時會以原切片容量的2倍的進行擴容; - 當擴容之后的元素長度大于
1024時會以原切片容量的1.25倍的進行擴容;
func main() {s6 := make([]int, 0)fmt.Printf("The capacity of s6: %d\n", cap(s6))for i := 1; i <= 10; i++ {s6 = append(s6, i)fmt.Printf("s6(%d): len: %d, cap: %d, address %p\n", i, len(s6), cap(s6), s6)}fmt.Println()
}
輸出結果如下:
The capacity of s6: 0
s6(1): len: 1, cap: 1, address 0xc0000160e8
s6(2): len: 2, cap: 2, address 0xc000016130
s6(3): len: 3, cap: 4, address 0xc0000145c0
s6(4): len: 4, cap: 4, address 0xc0000145c0
s6(5): len: 5, cap: 8, address 0xc00001c200
s6(6): len: 6, cap: 8, address 0xc00001c200
s6(7): len: 7, cap: 8, address 0xc00001c200
s6(8): len: 8, cap: 8, address 0xc00001c200
s6(9): len: 9, cap: 16, address 0xc00007a080
s6(10): len: 10, cap: 16, address 0xc00007a080
通過上面代碼我們可以得知:
- 當不需要擴容時,
append函數返回的是原底層數組的原切片(內存地址不變); - 當切片需要擴容時,
append函數返回的是新底層數組的新切片(切片內存地址發生了改變);
4. 對數組進行切片索引,不會改變原有數組
在一個數組上通過索引的方式生成新的切片后,對新的切片進行增加元素不會影響到原有的數組。如下代碼所示:
func main() {a1 := [7]int{1, 2, 3, 4, 5, 6, 7}fmt.Printf("a1: %v (len: %d, cap: %d)\n", a1, len(a1), cap(a1))s9 := a1[1:4]fmt.Printf("s9: %v (len: %d, cap: %d)\n", s9, len(s9), cap(s9))for i := 1; i <= 5; i++ {s9 = append(s9, i)fmt.Printf("s9(%d): %v (len: %d, cap: %d)\n", i, s9, len(s9), cap(s9))}fmt.Printf("a1: %v (len: %d, cap: %d)\n", a1, len(a1), cap(a1))
}
輸出結果為:
a1: [1 2 3 4 5 6 7] (len: 7, cap: 7)
s9: [2 3 4] (len: 3, cap: 6)
s9(1): [2 3 4 1] (len: 4, cap: 6)
s9(2): [2 3 4 1 2] (len: 5, cap: 6)
s9(3): [2 3 4 1 2 3] (len: 6, cap: 6)
s9(4): [2 3 4 1 2 3 4] (len: 7, cap: 12)
s9(5): [2 3 4 1 2 3 4 5] (len: 8, cap: 12)
a1: [1 2 3 4 1 2 3] (len: 7, cap: 7)
總結
以上是生活随笔為你收集整理的Go 知识点(15)— 切片长度和容量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国水处理分离膜行业
- 下一篇: 2022-2028年中国农用塑料薄膜行业