引用类型-1-切片
一 切片创建
切片(slice)解决了数组长度不能扩展,以及基本类型数组传递时产生副本的问题。
常用创建方式:
var s1 []int // 和声明数组一样,只是没有长度,但是这样做没有意义,因为底层的数组指针为nil
s2 := []byte {'a','b','c'}
fmt.Println(s1) //输出 []
fmt.Print(s2) //输出 [97 98 99]
使用make函数创建:
slice1 := make([]int,5) // 创建长度为5,容量为5,初始值为0的切片
slice2 := make([]int,5,7) // 创建长度为5,容量为7,初始值为0的切片
slice3 := []int{1,2,3,4,5} // 创建长度为5,容量为5,并已经初始化的切片
从数组创建:slice可以从一个数组再次声明。slice通过array[i:j]来获取,其中i是数组的开始位置,j是结束位置,但不包含array[j],它的长度是j-i:
// 声明一个含有10个元素元素类型为byte的数组
var arr = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// 声明两个含有byte的slice
var a, b []byte
// a指向数组的第3个元素开始,并到第五个元素结束,现在a含有的元素: ar[2]、ar[3]和ar[4]
a = arr[2:5]
// b是数组arr的另一个slicre,b的元素是:ar[3]和ar[4]
b = arr[3:5]
注意:声明数组时,方括号内写明了数组的长度或使用...自动计算长度,而声明slice时,方括号内没有任何字符。
从切片创建:
oldSlice := []int{1,2,3}
newSlice := oldSlice[:6] //基于切片前6个元素创建,没有的默认0
注意:如果选择的旧切片长度超出了旧切片的cap()值(切片存储长度),则不合法。
二 切片常见操作
2.1 切片常见内置函数
切片常用内置函数:
len() 返回切片长度
cap() 返回切片底层数组容量
append() 对切片追加元素
func copy(dst, src []Type) int
将src中数据拷贝到dst中,返回拷贝的元素个数
切片空间与元素个数:
slice1 := make([]int, 5, 10)
fmt.Println(len(slice1)) // 5
fmt.Println(cap(slice1)) // 10
fmt.Println(slice1) // [0 0 0 0 0]
切片操作
//切片增加
slice1 = append(slice1,1,2)
fmt.Println(slice1) //输出[0 0 0 0 0 1 2]
//切片增加一个新切片
sliceTemp := make([]int,3)
slice1 = append(slice1,sliceTemp...)
fmt.Println(slice1) //输出[0 0 0 0 0 1 2 0 0 0]
//切片拷贝
s1 := []int{1,3,6,9}
s2 := make([]int, 10) //必须给与充足的空间
num := copy(s2, s1)
fmt.Println(s1) //[1 3 6 9]
fmt.Println(s2) //[1 3 6 9 0 0 0 0 0 0]
fmt.Println(num) //4
//切片中删除元素
s1 := []int{1,3,6,9}
index := 2 //删除该位置元素
s1 = append(s1[:index], s1[index+1:]...)
fmt.Println(s1) //[1 3 9]
// 切片拷贝
s1 := []int{1,2,3,4,5}
s2 := []int{6,7,8}
copy(s1,s2) //复制s2前三个元素到slice1前3位置
copy(s2,s1) //复制s1前三个元素到slice2
注意:没有...会编译错误,默认第二个参数后是元素值,传入切片需要展开。如果追加的长度超过当前已分配的存储空间,切片会自动分配更大的内存。