切片是长度可变的数组(具有相同数据类型的数据项组成的一组长度可变的序列),切片由三部分组成:
- 指针: 指向切片第一个元素指向的数组元素的地址
- 长度: 切片元素的数量
- 容量: 切片开始到结束位置元素的数量
切片的语法和数组很类似。切片是建立在数组之上的,当申请一个切片的时候,底层是通过指针指向一个数组。
这个数组的长度是当前申请的切片可以存储多少元素,存储的元素也就是当前设值的值,等于容纳多少值。对于切片来讲,容纳多少值并不代表存储了多少值。需要存放多少值,而存放的值表示切片的长度。
在声明切片后,是通过指针操作的,而指针默认为nil
对于数据结构来讲,并不是等于nil,但当我们进行判断的时间,底层指向指针,为nil
var nums []int fmt.Println(nums == nil)结果为rue
4.1切片声明
切片声明需要指定元素组成的类型,但不需要指定存储元素的数量(长度)。如下:
var nums []int
在切片声明后,会被初始化为nil(零值),表示暂不存在的切片。如下:
- []int{} 空切片指的是底层数组没有存储元素
- var nums []int nil切片指的是底层数组是指向nil,没有申请内存空间的,在append的时候申请
package main
import "fmt"
func main(){
var nums []int
fmt.Printf("%#v",nums)
fmt.Printf("%T",nums)
}
运行
[root@www.linuxea.com /opt/Golang/work2]# go run slice.go
[]int(nil)
[]int
这里的nil和切片的长度和容量没有绝对的关系。这里的nil不是值等于nil,长度和容量有值后,这里的nil是指针的nil
4.2切片赋值
直接在进行赋值,如[]int{1,2,4,5},[]中不需要设置长度
如下:
package main
import "fmt"
func main(){
var nums []int
nums = []int{1,2,3,4}
fmt.Println(nums)
nums = []int{1,2,3,4,5}
fmt.Printf("%#v",nums)
}
运行:
[root@www.linuxea.com /opt/Golang/work2]# go run slice.go
[1 2 3 4]
[]int{1, 2, 3, 4, 5}
- 数组切片赋值
可以使用数组切片进行赋值
定义一个数组
var arrays [10]int = [10]int{1,2,3,4,5,6,7}
将arrays[1:10]赋值给nums
nums = arrays[1:10]
代码块:
package main
import "fmt"
func main(){
var nums []int
nums = []int{1,2,3,4}
fmt.Println(nums)
nums = []int{1,2,3,4,5}
fmt.Println(nums)
var arrays [10]int = [10]int{1,2,3,4,5,6,7}
nums = arrays[1:10]
fmt.Println(nums)
fmt.Printf("%#v",nums)
}
运行
[root@www.linuxea.com /opt/Golang/work2]# go run slice.go
[1 2 3 4]
[1 2 3 4 5]
[2 3 4 5 6 7 0 0 0]
[]int{2, 3, 4, 5, 6, 7, 0, 0, 0}
4.3切片长度和容量的获取
使用len获取长度,cap获取容量。如下:
package main
import "fmt"
func main(){
var nums []int
// fmt.Printf("%#v",nums)
//fmt.Printf("%T",nums)
nums = []int{1,2,3,4}
fmt.Println(nums)
nums = []int{1,2,3,4,5}
fmt.Println(nums)
var arrays [10]int = [10]int{1,2,3,4,5,6,7}
nums = arrays[1:10]
fmt.Printf("%#v,%d,%dn",nums,len(nums),cap(nums))
}
运行
[root@www.linuxea.com /opt/Golang/work2]# go run slice2.go
[1 2 3 4]
[1 2 3 4 5]
[]int{2, 3, 4, 5, 6, 7, 0, 0, 0},9,9
在这里可以看到len和cap都是一样的。那为什么还要有长度和容量?
4.4make函数
make函数第一个参数是用来指定类型,第二个元素是指定长度,第三个元素指定容量,也可以不指定,如果不指定长度和容量是一样的。如下:
nums := make([]int,3)
package main
import "fmt"
func main(){
nums := make([]int,3)
fmt.Printf("%#v %d %dn",nums,len(nums),cap(nums))
}
运行
[root@www.linuxea.com /opt/Golang/work2]# go run make.go
[]int{0, 0, 0} 3 3
这里可以看到这里有三个0。在切片中我们知道定义一个切片后他的值是nil,是因为底层指向一个指针。而make就是在指针进行赋值,在这里定义多大的长度的数组,初始化到切片中。这里的len是3,但是并没有存储值,所以在打印值的时候就是三个0。
- 始化容量
在上面我们并没有初始化容量,但是容量和长度却是一样的。现在初始化容量看看:
nums := make([]int,3,5)
package main
import "fmt"
func main(){
nums := make([]int,3,5)
fmt.Printf("%#v %d %dn",nums,len(nums),cap(nums))
}
运行
[root@www.linuxea.com /opt/Golang/work2]# go run make.go
[]int{0, 0, 0} 3 5
如上,当长度声明为5的时候,还是打印了三个0,而容量是5 。这是为什么?当容量为5,是说明可以存储的元素是5,而长度是已经存储的元素,所以这里打印的还是三个0。而剩下的两个元素,仍然可以使用。
并且,这里的容量会随着长度的不断增加而通过内置的算法进行自动变化的。