切片(slice)的定义
概念:
-
对数组的一个连续片段的引用,切片是一个引用类型
特点:
-
对"连续片段"
-
"引用"
(更类似于 C/C++
中的数组类型,或者 Python
中的 list 类型)
可以是整个数组,也可以是由起始和终止索引标识的一些项的子集
注意:
终止索引标识的项不包括在切片内。
示例:
package main
import "fmt"
func main() {
var a = [3]int{1, 2, 3}
fmt.Println(a, a[1:2])
}
/*
起始位置是:1
终止位置是:2
切片长度是:2-1
所以是从起始位置开始切掉切片长度数量的数展示
*/
Go中切片内部的结构
-
地址
-
大小
-
容量
作用:
-
一般用于快速地操作一块数据集合
切片结构和内存分配图:
数组或切片生成新的切片
切片默认指向一段连续内存区域,可以是数组,也可以是切片本身。
切片的声明格式:
slice [开始位置 : 结束位置]
语法说明格式:
-
slice:表示目标切片对象;
-
开始位置:对应目标切片对象的索引;
-
结束位置:对应目标切片的结束索引。
-
开始位置、结束位置,两者同时缺省时,与切片本身等效;
-
开始位置、结束位置,两者同时为 0 时,等效于空切片,一般用于切片复位。
根据索引位置取切片 slice 元素值时,取值范围是(0~len(slice)-1),超界会报运行时错误,生成切片时,结束位置可以填写 len(slice) 但不会报错。
示例:
package main
import "fmt"
func main() {
var a = [3]int{1, 2, 3}
fmt.Println(a, a[1:2])
fmt.Println(a[1:])
fmt.Println(a[:2])
fmt.Println(a[:])
}
从指定范围中生成切片
package main
import "fmt"
func main() {
var array [30]int
for i := 0; i < 30; i++ {
array[i] = i+1
}
//区间内的值
fmt.Println(array[10:20])
//中间到尾部的所有元素
fmt.Println(array[15:])
//开头到中间指定位置的值
fmt.Println(array[:15])
}
表示原有的切片
忽略开始和结束的位置:
package main
import "fmt"
func main() {
a := []int{1,2,3}
fmt.Println(a[:])
}
/*
输出的结果是原数组本身
*/
重置切片,清空拥有的元素
package main
import "fmt"
func main() {
a := []int{1,2,3}
fmt.Println(a[:])
fmt.Println(a[0:0])
fmt.Println(a)
}
/*
重置只会重置切片空间内的值
切片相当于重新开辟了一块空白的区域,放入连续的内存空间用于计算
*/
直接声明新的切片
Go中除了可以在原有的数组或切片中生成切片以外也可以声明一个切片。
var name []Type
-
name 表示切片的变量名
-
Type 表示切片对应的元素类型。
因为切片是操作一部分连续的内存空间,所以声明一个切片的格式和声明一个数组类型:
package main
import "fmt"
func main() {
//字符串型切片
var strList []string
//整型切片
var numList []int
//空切片--->空数组是对变量赋值不是声明变量
var emptyList = []int{}
fmt.Println(strList, numList, emptyList) ////emptyList 已经被分配了内存,只是还没有元素。
fmt.Println(len(strList), len(numList), len(emptyList))
fmt.Println(strList == nil)
fmt.Println(emptyList == nil)
/*切片是动态结构,只能与 nil 判定相等,不能互相判定相等。声明新的切片后,可以使用 `append()` 函数向切片中添加元素*/
}
切片是动态结构,只能与 nil 判定相等,不能互相判定相等。声明新的切片后,可以使用 append()
函数向切片中添加元素。
使用make()函数构造切片
动态地创建一个切片,可以使用 make() 内建函数
make( []Type, size, cap )
-
Type 是指切片的元素类型
-
size 指的是为这个类型分配多少个元素
-
cap 为预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题。
示例:
package main
import "fmt"
func main() {
a := make([]int, 3)
b := make([]int, 4, 10)
fmt.Println(a, b)
fmt.Println(len(a), len(b))
}
效果图:
代码分析:
其中 a 和 b 均是预分配 2 个元素的切片,只是 b 的内部存储空间已经分配了 10 个,但实际使用了 2 个元素。
容量不会影响当前的元素个数,因此 a 和 b 取 len 都是 2。
-
一旦使用
make()
函数生成切片一定发生了内存分配操作 -