数组(array)
定义
Go语言提供了数组类型的数据结构。数组是具有相同类型的一组长度固定的数据序列,这种类型可以使任意的基本数据类型或复合数据类型及自定义类型。
数组元素可以通过索引下标(位置)来读取或修改元素数据。索引从0开始,第一个元素索引为0,第二个索引为1,以此类推。数组的下标取值范围是从0开始,到长度减1。
数组一旦定义后,大小不能更改。
语法
声明数组
Go语言数组声明需要制定元素类型及元素个数,
- var 变量名 [数组长度]数据类型 // 一维数组定义
- 数组长度必须是整数且大于0
- 为初始化的数组不是nil,也就是没有空数组(与切片不同)
初始化数组
- var nums =[5]int{1,2,3,4,5}
- 初始化数组中{}中的元素个数不能大于[]中的数字
- 如果忽略[]中的数字不设置数组大小,Go语言会根据元素的个数来设置数组的大小。
- 可以忽略声明中数组的长度并将其替换为…。编译器会自动计算长度
- var nums = […]int{1,2,3}
- 该实例与上面的实例是一样的,虽然没有设置数组的大小
数组长度
通过将数组作为参数传递给len()函数,可以获得数组的长度。
数组是值类型
Go语言中的数组是值类型,而不是引用类型。这意味着当它们被分配一个新变量是,将把原始数组的副本分配给新变量。如果对新变量进行了更改,则不会再原始数组中反映。
当将数组传递给函数作为参数时,将通过值传递,而原始数组将保持不变。
切片(slice)
定义
Go语言切片是对数组的抽象。
- Go数组的长度不可改变,在特定场景中这样的集合就不太方便,Go中提供了一种灵活,功能强悍的内置类型切片(“动态数组”)
- 与数组相比切片的长度是不固定的,可以追加元素。在追加时可能使切片的容量增大
- 切片本身没有任何数据,只是对现有数组的引用
- 切片与数组相比,不需要设定长度,在[]中不用设定值,相对来说比较自由
- 从概念上slice像一个结构体,这个结构体包含了三个元素
- 指针,指向数组中slice指定的开始位置
- 长度,即slice的长度
- 最大长度,也就是slice开始位置到数组的最后位置的长度
语法
声明变量
- 声明一个未指定长度的数组来定义一个切片
- var identifier []type
- 切片不需要说明长度
- 该声明方式,且未初始化的切片为空切片。该切片默认为nil,长度为o.
- 使用make()函数创建切片
- var slice1 []type - make([]type,len)
- 简写为 slice := make([]type,len)
- 可以指定容量 make([]T,length,capacity)
初始化
-
直接初始化
s :=[]int{1,2,3}
-
通过数组截取来初始化切片
//声明数组
arr :=[5]int{1,2,3,4,5}
s := arr[:] //切片中包含数组所有元素
s := arr[startIndex:endIndex] // 将arr中从下标startIndex到endIndex-1下的元素创建一个新的切片(前闭后开)
s := arr[startIndex:] //缺省endIndex时表示一直到arr的最后一个元素
s := arr[:endIndex] //缺省startIndex时将表示从arr的第一个元素开始
s := arr[startIndex:endIndex:max] //显示的指定最大值 没有显示的指定时默认为数组长度
s := arr[:endIndex:max] // 缺省startIndex时表示从arr的第一个元素开始
```
3.也可以通过切片在切片上初始化切片
nums := []int{10,20,5:30}
s :=[1:]
源码
type slice struct{
array .Pointer
len int
cap int
}
切片(slice)本身并非动态数据或指针数组。它内部通过指针引用底层数组,设定相关属性将数据读写操作限定在指定区域内。
切片本身只是个读对象,其工作机制类似于数组指针的一种包装。
属性cap表示切片所引用数组片段的真实长度,len用于限定可读的写元素数量。
通过在数组上截取的切片的len和cap属性计算公式如下:
len = endInex -startIndex
cap = max - startIndex
可直接创建切片对象,无需预先准备数组,因为切片是引用类型,需使用make()函数或显示初始化语句,它会自动完成底层数组内存分配。
func mian(){
s1 := make([]int,3,5) //指定len,cap,底层数组初始化为零值
s2 := make([]int,3) // 省略cap,和len相等
s3 := []int{10,20,4:30} // [10,20,0,0,30]
}
切片 只是很小的结构体对象,用来代替数组传参可避免复制开销。make允许在运行期动态指定数组长度,绕开了数组类型必须使用编译期常量的限制。
并非所有时候都适合用切片代替数组,应为切片底层数组可能会在堆上分配内存。而且小数组在栈上拷贝的消耗未必比make小。
len()和cap()函数
- 切片的长度是切片中元素的数量
- 切片的容量是从创建切片的索引开始的底层数组中元素的数量
- 切片实可索引的,并且可以由len()方法获取长度,切片提供了计算容量的方法cap(),可以测量切片最长可以达到多少
- cap()的结果决定了切片截取得注意细节
append()和copy()函数
- append()
- 往切片中追加新元素
- 可以往slice里面追加一个或者多个元素,也可以追加一个切片
- append函数会改变slice引用的数组的内容,从而影响到引用同一组数组的其他slice
- 当使用append追加元素到切片是,如果容量不够,Go就会创建一个新的内存地址来存储元素
- copy()
- 复制切片元素
- 将源切片的元素复制到目标切片中,返回复制的元素个数
- copy方法是不会建立源切片与目标切片之间的联系,一个修改不影响另一个。