切片就是一个可以没有长度限制的数组,很灵活,支持自动扩缩容,它是基于数组类型做的一层封装
它的内部结构包括地址,长度和容量。切片一般用于快速操作一块数据集合。
定义一个切片
//var 切片名 []切片类型
package main
import "fmt"
func main() {
var a1 []int
var a2 []int
fmt.Println(a1, a2) //这里打印出来的是[][]
}
切片的初始化
package main
import "fmt"
func main() {
var a1 []int
var a2 []string
a1 = []int{1, 2, 3}
a2 = []string{"openstack", "kubernetes", "容器"}
fmt.Println(a1, a2)
}
切片在未定义具体数值时为其内部的数值为空,也就是没在内存上有空间存储
切片的长度和容量
切片有自己的长度和容量,我们可以通过内置的len()函数求长度,使用内置的cap()函数求切片的容量
package main
import "fmt"
func main() {
var a1 []int
var a2 []string
a1 = []int{1, 2, 3}
a2 = []string{"openstack", "kubernetes", "容器"}
fmt.Println(a1, a2)
fmt.Printf("%d %d\n", len(a1), len(a2))
fmt.Printf("%d %d", cap(a1), cap(a2))
}
由数组得到切片
package main
import "fmt"
func main() {
a1 := [...]int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19}
a2 := a1[0:4] //左闭右开,基于数组的切割
fmt.Println(a2)
a3 := a1[:4] // = [0:4]
a4 := a1[3:] // =[3:len(a1)]
a5 := a1[:] // =[0:len(a1)]
fmt.Printf("a3= %d \na4= %d \na5= %d\n", a3, a4, a5)
// 切片的长度根据切完的数组来定,容量是根据最开始切的那个数,按照底层数组来算到最后一个数来算总量
// 例如a3
fmt.Printf("a3长度为%d,a3容量为%d\n", len(a3), cap(a3)) //这里容量就是0到10
fmt.Printf("a4长度为%d,a4容量为%d\n", len(a4), cap(a4)) //这里容量就是3到10
fmt.Printf("a5长度为%d,a5容量为%d\n", len(a5), cap(a5))
}
切片指向了一个底层的数组
切片的长度就是它元素的个数
切片的容量是底层数组从切片的第一个元素到最后一个元素的数量。
切片可以进行扩容,它容量是不会被底层数组所限制
切片再切割
package main
import "fmt"
func main() {
a1 := []int{1, 3, 5, 7, 9, 11}
a2 := a1[3:]
a3 := a2[2:]
fmt.Println("a2的值为:", a2, "a3的值为:", a3)
fmt.Printf("a2切片的长度为:%d,a2切片的容量为:%d\n", len(a2), cap(a2))
fmt.Printf("a3切片的长度为:%d,a3切片的容量为:%d", len(a3), cap(a3))
//修改a1的数据
fmt.Println(a1)
a1[5] = 1111111
fmt.Println(a1)
fmt.Println(a2)
//再看一下a3
fmt.Println(a3)
//所以切片只是引用了数组的值数组值发生修改就会引起切片数值发生修改
}
使用make函数
切片名 := make([]切片类型,切片长度,切片容量)
package main
import "fmt"
func main() {
a1 := make([]int, 5, 10)
fmt.Printf("a1的值是:%d\na1的长度为:%d\na1的容量为:%d\n", a1, len(a1), cap(a1))
//如果不指定make函数中的10,默认容量为5
a2 := make([]int, 5)
fmt.Printf("a2的值是:%d\na2的长度为:%d\na2的容量为:%d\n", a2, len(a2), cap(a2))
}
容量是占用的意思和长度无关
a3 := make([]int, 0, 10)
//这里打印的是空的数组,容量就是占用了10个数据长度
fmt.Printf("a2的值是:%d\na2的长度为:%d\na2的容量为:%d\n", a3, len(a3), cap(a3))
切片不能直接比较
切片直接是不能比较的,我们不能使用==操作符来判断两个切片是否含有全部相等元素。切片唯一合法的比较炒作是和nil比较。一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0.但是我们不能说一个长度和容量都是0的切片一定是nil,例如下面的实例
就是你有切片就算没值也是有内存地址了,nil虽然也是空值但是它是没有内存地址
var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int,0) //len(s3)=0;cap(s3)=0;s3!=nil
所以要判断一个切片是否是空的,要用len(s) ==0来判断,不应该使用s == nil来判断
切片的遍历
package main
import "fmt"
func main() {
a2 := []int{1, 2, 3, 4, 5, 6, 7}
a1 := make([]int, 5, 10)
a1 = a2
for i := 0; i < len(a1); i++ {
fmt.Println(a1[i])
}
for k, v := range a1 {
fmt.Println(k, v)
}
}
切片的本质
切片就是一个框,框住了一块连续的内存
切片是引用类型,它的所有数据都是指向底层数组数据,底层数据发生修改切片的数组也会发送改变