声明:
package main
import "fmt"
func main() {
// 数组声明
s1 := make([]int,5)
fmt.Printf("The length of s1: %d\n", len(s1)) //5
fmt.Printf("The capacity of s1: %d\n", cap(s1)) //5
fmt.Printf("The value of s1: %d\n", s1) // [0 0 0 0 0]
s4 := [5]int{0,1,2}
fmt.Printf("The length of s4: %d\n", len(s4)) //5
fmt.Printf("The capacity of s4: %d\n", cap(s4)) //5
fmt.Printf("The value of s4: %d\n", s4) // [0 1 2 0 0]
// 切片声明
s2 := make([]int, 5, 8)
fmt.Printf("The length of s2: %d\n", len(s2)) //5
fmt.Printf("The capacity of s2: %d\n", cap(s2)) //8
fmt.Printf("The value of s2: %d\n", s2) // [0 0 0 0 0]
s3 := []int{0,1,2,3,4}
fmt.Printf("The length of s3: %d\n", len(s3)) //5
fmt.Printf("The capacity of s3: %d\n", cap(s3)) //5
fmt.Printf("The value of s3: %d\n", s3) // [0 1 2 3 4]
}
数组的长度是不可变的,而切片的长度是可变的,他的底层数据结构是一个数组。数组可以被叫做切片的底层数组,而切片也可以被看做是对数组的某个连续片段的引用。
数组的容量永远等于其长度,都是不可变的。切片的容量却不是这样,一旦一个切片无法容纳更多的元素,go语言就会想办法扩容。但它并不会改变原来不的切片,而时会生成一个容量更大的切片,然后将原有的元素和新元素一并拷贝到新切片中。在一般情况下,新切片容量将会是旧切片容量的2倍,但是当原切片的长度大于等于1024时,go语言将会以原容量的1.25倍作为新容量的基准。
虽然在扩容的时候go语言一定会生成新的底层数组,但是它也同事生成了新的切片。它只是把新的切片作为了新底层的窗口,而没有对原切片及其底层数组做任何改动。
package main
import "fmt"
func main() {
//数组的扩容是2倍增加
s1:=[]int{0,1,2,3}
fmt.Printf("The length of s1: %d\n", len(s1)) //4
fmt.Printf("The capacity of s1: %d\n", cap(s1)) //4
fmt.Printf("The value of s1: %d\n", s1) // [0 1 2 3]
s1=append(s1, 4)
fmt.Printf("The length of s1: %d\n", len(s1)) //5
fmt.Printf("The capacity of s1: %d\n", cap(s1)) //8
fmt.Printf("The value of s1: %d\n", s1) // [0 1 2 3 4]
//浅拷贝
s2:=s1[0:len(s1)]
s2[0]=11
fmt.Printf("The value of s2[0]: %d\n", s2[0]) //11
fmt.Printf("The value of s1[0]: %d\n", s1[0]) //11
//深拷贝
// copy 函数提供深拷贝功能
// 但需要在拷贝前申请空间
s3 := make([]int, 5, 5)
copy(s3, s1)
s3[0]=111
fmt.Printf("The value of s3[0]: %d\n", s3[0]) //111
fmt.Printf("The value of s1[0]: %d\n", s1[0]) //11
}
切片的缩容:
package main
import "fmt"
func main() {
s1:=[]int{0,1,2,3,4,5,6,7,8}
fmt.Printf("The length of s1: %d\n", len(s1)) //9
fmt.Printf("The capacity of s1: %d\n", cap(s1)) //9
fmt.Printf("The value of s1: %d\n", s1) // [0 1 2 3 4 5 6 7 8]
//删除切片元素remove element at index
index:=5;
s1=append(s1[:index-3],s1[index+3:]...)
fmt.Printf("The length of s1: %d\n", len(s1)) //3
fmt.Printf("The capacity of s1: %d\n", cap(s1)) //9
fmt.Printf("The value of s1: %d\n", s1) // [0 1 8]
//可以看到切片缩容之后还是会引用底层的原数组,
// 这有时候会造成大量缩容之后的多余内容没有被垃圾回收。
// 可以使用新建一个数组然后copy的方式。
s2:=make([]int,3,3)
copy(s2,s1)
fmt.Printf("The length of s2: %d\n", len(s2)) //3
fmt.Printf("The capacity of s2: %d\n", cap(s2)) //3
fmt.Printf("The value of s2: %d\n", s2) // [0 1 8]
}