什么是切片
切片是 Golang 中比较特殊的数据结构,这种数据结构更便于使用和管理数据集合。简单的说,切片就是一种简化版的动态数组。因为动态数组的长度不固定,所以切片的长度自然也就不能是类型的组成部分了。切片是围绕动态数组的概念构建的,是对数组的抽象。数组虽然有适用的地方,但是数组的类型和操作都不够灵活,因此在 Go 代码中数组使用的并不是很多,而切片则使用的相当广泛,理解切片的原理和用法相当重要。
切片的内部结构
我们先来看看切片的结构定义,即 reflect.SliceHeader:
type SliceHeader struct {
Data unitptr
Len int
Cap int
}
由切片的结构定义可知,切片的结构由三个信息组成:
指针,指向底层数组中切片指定的开始位置
长度,即切片的长度
最大长度,也就是切片开始位置到数组的最后位置的长度
下图给出了切片 x := [2, 3, 5, 7, 9, 11, 13, 15] 和 y := [1:3] 两个切片对应的内存结构。
切片的创建和初始化
让我们看看切片有哪些创建和初始化的方式:
var(
a []int // nil 切片,和 nil 相等,一般用来表示一个不存在的切片
b = []int{} // 空切片,和 nil 不相等,一般用来表示一个空的集合
c = []int{1, 2, 3, 4} // 有 4 个元素的切片,len 和 cap 都为 4
d = c[:2] // 有 2 个元素的切片,len 为 2,cap 为 4
e = c[0:2:cap(c)] // 有 2 个元素的切片,len 为 2,cap 为 4
f = c[:0] // 有 0 个元素的切片,len 为 0,cap 为 4
g = make([]int, 3) // 有 3 个元素的切片,len 和 cap 都为 3
h = make([]int, 3, 5) // 有 3 个元素的切片,len 为 3,cap 为 5
i = make([]int, 0, 5) // 有 0 个元素的切片,len 为 0,cap 为 5
)
使用 Golang 内置的函数 len() 可以查看切片中有效元素的长度,内置的函数 cap() 可以查看切片容量大小。
修改切片
切片没有自己的任何数据,它只是底层数组的一个表示。对切片所做的任何修改都将反映在底层数组中。
示例代码:
package main
import (
"fmt"
)
func main() {
darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
dslice := darr[2:5]
fmt.Println("array before",darr)
for i := range dslice {
dslice[i]++
}
fmt.Println("array after",darr)
}
运行结果:
array before [57 89 90 82 100 78 67 69 59]
array after [57 89 91 83 101 78 67 69 59]
当多个片共享相同的底层数组时,每个元素所做的更改将在数组中反映出来。
示例代码:
package main
import (
"fmt"
)
func main() {
numa := [3]int{78, 79 ,80}
nums1 := numa[:] //creates a slice which contains all elements of the array
nums2 := numa[:]
fmt.Println("array before change 1",numa)
nums1[0] = 100
fmt.Println("array after modification to slice nums1", numa)
nums2[1] = 101
fmt.Println("array after modification to slice nums2", numa)
}
运行结果:
array before change 1 [78 79 80]
array after modification to slice nums1 [100 79 80]
array after modification to slice nums2 [100 101 80]
有疑问加站长微信联系(非本文作者)