var s1 []int //nil切片,s1 == nil 返回true,len为0,cap为0,底层数组指针不指向任何地址,官方建议使用此方式
s1 := []int{} //空切片,s1 == nil返回false,len为0,cap为0,底层数组指针指向一个地址
s1 = append(s1,1) //追加一个元素
s1 = append(s1,[]int{2,3})//追另外整个切片的内容
len(s1) //获取切片长度
cap(s1)//获取切片容量
s2 := s1[1:2] //s2为[1]
s3 := s1[0:] //s3为[1,2,3]
s4 := s1[:2] //s4为[1,2]
s5 := s1[:] //s5为[1,2,3]
type slice struct {
array unsafe.Pointer //数组指针
len int //切片的长度
cap int //切片的容量
}
切片是一个结构体,有3个元素,分别是保存数组地址的指针,切片长度,切片容量,由于切片底层共享一个数组,可能会出现操作一个切片而影响到其他切片的情况发生
很经典一例子,引用自《Go学习笔记》第四版
package main
import "fmt"
func main() {
slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := slice[2:5] //切片s1元素为[2,3,4],截取时为左开右闭区间,所以不包括第5个元素,长度为3,容量为新切片的第一个元素到原始切片底层数组最后一个元素为8
s2 := s1[2:6:7]// 切片s2元素为[4,5,6,7],长度为4,容量到s1的索引7,即容量为5
s2 = append(s2, 100)//向s2追加一个元素100,此时s2为[4,5,6,7,100]
s2 = append(s2, 200)//继续向s2追加一个元素100,此时因为s2的容量已满,会发生扩容为原来的容量的2倍,及容量为10
s1[2] = 20 //向s1追加一个元素20,此时并不会影响s2,因为扩容后,s2指向的底层数组并不和s2相同,扩容时会将s2的指向的数组片度复制到新的底层数组,即扩容后s1和s2不再指向同一个底层数组
fmt.Println(s1) //打印结果为[2 3 20]
fmt.Println(s2) //打印结果为[4 5 6 7 100 200]
fmt.Println(slice) //打印结果为[0 1 2 3 20 5 6 7 100 9]
}
切片扩容规律为:当追加元素时容量超出当前切片最大容量,当前的元素长度小于1024,扩展为当前容量的2倍,当大于1024时会进行内存对齐,扩容后的容量 >= 原容量的 2 倍或 1.25 倍
参考: