Go语言基础之数组切片
目录:
概述
基于数组,数组切片天界了一系列管理功能,可以随时动态扩充存放空间,并且可以随意传递而不会导致所管理的元素被重复复制。
数组切片的数据结构可以抽象为以下3个变量:
- 一个指向原生数组的指针
- 数组切片中的元素个数
- 数组切片已分配的存储空间
创建数组切片
创建数组切片的方法主要有两种:
基于数组
数组切片可以基于一个已存在的数组创建,数组切片可以只使用数组的一部分元素或者整个数组来创建。
package main
import (
"fmt"
)
func main() {
var array1 = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var arraySlice = array1[:5]
fmt.Println("elements of array1:")
for _, v := range array1 {
fmt.Print(v, " ")
}
fmt.Println("
elements of arraySlice:")
for _, v := range arraySlice {
fmt.Print(v, " ")
}
}
通过数组的下标范围,创建切片
直接创建
通过内置函数make()
可以灵活的创建数组切片。
mySlice := make([]int, 5) //创建一个初始元素为5的数组切片,元素的初始值为0,
mySlice1 := make([]int, 5, 10) //创建一个初始元素为5的数组切片,元素的初始值为0,并预留10个元素的存储空间
mySlice2 := []int{1, 2, 3, 4, 5} //直接创建并初始化包含5个元素的数组切片。
元素遍历
操作数组元素的所有方法都适用于数组切片,数组切片也可以按下标读写元素,用len()
函数操作元素个数,支持使用range关键字快速遍历所有元素。
动态增减元素
可动态增减元素个数是数组切片比数组更为强大的功能。与数组相比,数组切片多了一个存储能力(capacity)的概念,即元素个数和分配空间可以是两个不同的值。合理的设置存储能力的值,可以大幅降低数组切片内部重新分配内存块的频率,从而大大提高程序的性能。
数组切片支持GO语言内置的cap()
和len()
函数,cap()
函数返回的是数组切片分配的空间大小,len()
函数返回的是数组切片中当前所存储的元素个数。
package main
import "fmt"
func main() {
slice1 := make([]int, 5, 10)
fmt.Println("len(slice1):", len(slice1))
fmt.Println("cap(slice1):", cap(slice1))
}
// len(slice1): 5
// cap(slice1): 10
数组切片通过append()
函数添加元素,其中,第二个参数是一个不定参数,可根据需求添加如干个元素。甚至可以直接将一个数组切片追加到一个数组切片的末尾
slice1 = append(slice1, 1, 2, 3, 4)
slice2 := []int{8, 9}
slice1 = append(slice1, slice2...)
需要注意的是slice2...
中的...
,如果没有这个省略号,则会编译报错,这里的左右就是将slice2
包含的所有元素打散后传入slice1
。
数组切片会自动处理存储空间不足的问题。可以通过查看$GOROOT/src/runtime/slice.go源码,其中扩容相关代码如下:
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
基于数组切片创建数组切片
类似于数组切片可以基于一个数组创建,数组切片也可以基于另一个数组切片创建。
oldSlice := []int{1, 2, 3, 4, 5}
newSlice := oldSlice[:3]
其中,选择oldSlice的元素范围可以超过所以包含的元素个数,但是不能超过oldSlice的存储能力(cap()返回的值),超出oldSlice元素的个数部分会使用0补充。
内容复制
通过内置函数copy()
,将内容从一个数组切片复制到另一个数组切片。如果两个数组切片不一样大,则会按照较小的数组切片的元素个数进行复制。
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
cpoy(slice2, slice1) //只会将slice1的前三个元素复制到slice2中
cpoy(slice1, slice2) //只会将slice2的三个元素复制到slice1的前三个位置