1. 创建切片
//定义一个空切片,注意[]中没有指定长度,如果指定长度,就代表是数组了
var slice []int
fmt.Println(slice) //[]
// 申明slice时,建议使用var方式申明,不建议使用大括号的方式,var方式申明在slice不被append的情况下避免了内存分配
GOOD: var t []string
BAD: t := []string{}
// 在一个nil的slice中添加元素是没问题的,但对一个nil map做同样的事将会生成一个运行时的panic
var s []int
s = append(s,1) // 正确
//创建一个长度和容量为5的切片
slice1 := []int{1, 2, 3, 4, 5}
fmt.Println(slice1) //[1 2 3 4 5]
fmt.Println(len(slice1), cap(slice1)) //5 5
//创建一个长度和容量为6的切片
slice2 := []int{5: 10}
fmt.Println(slice2) //[0 0 0 0 0 10]
fmt.Println(len(slice2), cap(slice2)) //6 6
//使用make创建切片
//make(type,len,cap),未指定cap是,cap和len相等
slice3 := make([]int, 5, 10)
fmt.Println(slice3, len(slice3), cap(slice3)) //[0 0 0 0 0] 5 10
slice4 := make([]int, 6)
fmt.Println(slice4, len(slice4), cap(slice4)) //[0 0 0 0 0 0] 6 6
//利用数组创建切片
//[strat:end]左闭右开,start省略时,默认为0;end省略时默认为数组或者切片长度
arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice5 := arr[3:]
fmt.Println(slice5) //[3 4 5 6 7 8 9]
slice6 := arr[:7]
fmt.Println(slice6) //[0 1 2 3 4 5 6]
slice7 := arr[4:8]
fmt.Println(slice7) //[4 5 6 7]
slice8 := arr[:]
fmt.Println(slice8) //[0 1 2 3 4 5 6 7 8 9]
2. len()函数
通过len函数求切片长度,判断是否为空。
3. append()函数
// 使用append函数后,返回的是一个slice类型,不是数组类型
// 不能对数组调用append函数,即append函数的第一个参数必须是slice。
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice) //[1 2 3 4 5]
//追加元素
slice = append(slice, 6)
fmt.Println(slice) //[1 2 3 4 5 6]
//追加切片
s1 := []int{99, 100}
//注意下面的...表示解构,即,将切片的内容展开后填充到该位置
slice = append(slice, s1...)
fmt.Println(slice)
4. copy()函数
// copy(destination,resource),复制之后,dest的长度并不会改变,即使复制给他的切片长度远大于它。
// 不能使用copy进行数组的复制操作,即,copy的两个参数都必须是slice。
//长的slice复制到短的slice
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{10, 20, 30, 40}
copy(s2, s1)
fmt.Println(s2) //[1 2 3 4]
//短的slice复制到长的slice
s3 := []int{2, 3, 4}
s4 := []int{9, 8, 7, 6, 5}
copy(s4, s3)
fmt.Println(s4) //[2 3 4 6 5]
//相同长度的slice进行复制
s5 := []int{1, 2, 3}
s6 := []int{4, 5, 6}
copy(s6, s5)
fmt.Println(s6) //[1 2 3]
5. 作为函数参数
package main
import "fmt"
//参数是数组类型
func Double(arr [5]int) {
for i := 0; i < 5; i++ {
arr[i] *= 2
}
}
//参数是slice类型
func Triple(slice []int) {
for i := 0; i < len(slice); i++ {
slice[i] *= 3
}
}
func main() {
arr := [5]int{1, 2, 3, 4, 5}
Double(arr)
fmt.Println(arr) //[1 2 3 4 5]
//数组转换为切片
slice := arr[:]
Triple(slice)
fmt.Println(arr) //[3 6 9 12 15]
}
6. reslice操作
package main
import "fmt"
func main() {
slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
fmt.Println(slice, len(slice), cap(slice)) //[0 1 2 3 4 5 6 7 8] 9 9
newSlice := slice[6:8]
fmt.Println(newSlice, len(newSlice), cap(newSlice)) //[6 7] 2 3
//向newSlice中添加一个元素,注意此时,刚好len(newSlice) == cap(newSlice)
newSlice = append(newSlice, 111)
fmt.Println(slice, len(slice), cap(slice)) //[0 1 2 3 4 5 6 7 111] 9 9
fmt.Println(newSlice, len(newSlice), cap(newSlice)) //[6 7 111] 3 3
//再向newSlice中添加一个元素,注意此时,
//刚好向后扩展newSlice时,已经超过了原slice的cap,超过的部分,不会反映到原slice
newSlice = append(newSlice, 222)
fmt.Println(slice, len(slice), cap(slice)) //[0 1 2 3 4 5 6 7 111] 9 9
fmt.Println(newSlice, len(newSlice), cap(newSlice)) //[6 7 111 222] 4 6
}
综上所述:当我们调用append向一个新的slice添加元素时:
如果新的slice在append之后,新slice的cap没有改变(即新slice的len仍小于新slice的cap),那么,至少在cap改变之前,append的行为结果都会反映到原slice
如果新的slice在append之后,新slice的cap改变了,那么,新的slice就拥有了自己的底层数组,所以,append的行为结果不会反映到原slice,但是cap没有改变之前,仍会反映到原slice,只是在cap改变之后,才不会反映到slice