切片
? Go語言切片是一種建立在陣列型別之上的抽象,它構建在陣列之上并且提供更強大的能力和便捷,解決了陣列長度不可變等缺陷
宣告切片
? 切片的資料結構非常小,只有三個欄位:指向底層陣列的指標,切片長度,切片容量,切片長度是指切片的真實長度,切片容量是指切片可擴展的最大長度,一般來講切片長度要小于等于底層陣列的長度也就是切片容量
? cap()用來計算切片容量,len()用來計算切片長度,所以有0 <= len() <= cap()
var 切片名 + [] + 資料型別(宣告切片但不初始化,那么這個切片的默認值為nil,長度為 0)
var slice []int
slice := make([]資料型別,切片長度,切片容量)(使用make()來宣告切片)
// 宣告一個長度為10,容量為20的切片slice
slice := make([]int, 10, 20)
// 因為切片長度為10 所以只能訪問10個元素,剩下的10個需要進行切片擴容之后才能使用
slice := []資料型別{初始化}
// 宣告時初始化
slice := []int{0,1,2,3,4,5,6,7,8,9}
// 同陣列一樣,切片也可以對單一元素賦值
slice := []int{3:9,5:10}
- 基于現有的陣列或切片,創建切片
// 創建底層陣列array
array := [10]int{0,1,2,3,4,5,6,7,8,9}
// 以array 為底層陣列創建切片slice,切片從索引3開始到索引9結束(并不包括索引9)
slice := array[3,9]
// 輸出slice的長度和容量
fmt.Printf("切片長度:%d\n", len(slice)) // 6
fmt.Printf("切片容量:%d\n", cap(slice)) // 7
// slice := array[i,j]
// 切片長度(j-i):9 - 3 = 6
// 切片容量(底層陣列長度 - i):10 - 3 = 7
// 也可以直接限制切片容量
slice := array[2,9,7]
fmt.Printf("切片長度:%d\n", len(slice)) // 7
fmt.Printf("切片容量:%d\n", cap(slice)) // 7
切片使用
? 使用切片,和使用陣列一樣,通過索引就可以獲取切片對應元素的值,同樣也可以修改對應元素的值
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := arr[3:9]
slice[3] = 100
fmt.Println(arr) // [0 1 2 3 4 5 100 7 8 9]
?:因為切片是對部分底層陣列的參考,所以修改切片的值,實際上是修改切片對應底層陣列的值
遍歷切片(for range)
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := arr[3:9]
// i:切片下標 j: 下標對應的值
for i, j := range slice {
fmt.Printf("%d : %d \n", i, j)
}
擴展切片
直接擴展slice = slice[0 : len(slice)+1]
? 切片可以反復擴展直到占據整個相關陣列,但是不能超過相關陣列長度!!!!!
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := arr[3:8]
fmt.Printf("slice長度:%d\n", len(slice))// 5
fmt.Printf("slice容量:%d\n", cap(slice))// 7
for i, j := range slice {
fmt.Printf("%d : %d \n", i, j)
}
slice = slice[0 : len(slice)+1]
fmt.Printf("slice長度:%d\n", len(slice))// 6
fmt.Printf("slice容量:%d\n", cap(slice))// 7
for i, j := range slice {
fmt.Printf("%d : %d \n", i, j)
}
append擴展
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
for i := range arr {
fmt.Printf("arr[%d]: %p\n", i, &arr[i])
}// 0xc0000ac0f0 ~~ 0xc0000ac138
// 在以arr為底層陣列創建切片slice,切片內元素的地址與陣列內元素地址相同
slice := arr[3:9]
fmt.Printf("slice長度:%d\n", len(slice))// 6
fmt.Printf("slice容量:%d\n", cap(slice))// 7
for i := range slice {
fmt.Printf("slice[%d]: %p\n", i, &slice[i])
}// 0xc0000ac108 ~~ 0xc0000ac130
// 使用append()在arr后面擴展一位,保持切片長度仍小于切片容量,切片內元素的地址與陣列內元素地址依舊相同,切片長度加一,切片容量不變
newSlice1 := append(slice, 9)
fmt.Printf("newSlice1長度:%d\n", len(newSlice1))// 7
fmt.Printf("newSlice1容量:%d\n", cap(newSlice1))// 7
for i := range newSlice1 {
fmt.Printf("newSlice1[%d]: %p\n", i, &newSlice1[i])
}// 0xc0000ac108 ~~ 0xc0000ac138
// 使用append()在arr后面擴展三位,導致切片長度大于原來的切片容量,切片內元素的地址與陣列內元素地址完全不同,切片長度加三,切片容量翻倍
newSlice2 := append(slice, 9, 10, 11)
fmt.Printf("newSlice2長度:%d\n", len(newSlice2))// 9
fmt.Printf("newSlice2容量:%d\n", cap(newSlice2))// 14
for i := range newSlice2 {
fmt.Printf("newSlice2[%d]: %p\n", i, &newSlice2[i])
}// 0xc0000d4000 ~~ 0xc0000d4040
?:當切片擴展時,切片長度大于原切片的切片容量,就會新建一個底層陣列,把原來陣列的值復制到新底層陣列里,再追加新值,這時候就不會影響原來的底層陣列了,append函式會智能的增長底層陣列的容量,目前的演算法是:容量小于1000個時,總是成倍的增長,一旦容量超過1000個,增長因子設為1.25,也就是說每次會增加25%的容量
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/549210.html
標籤:Go
上一篇:Go語言入門3(陣列)
下一篇:JVM的垃圾收集演算法
