Arrays AND Slices
概述
Array(数组) 与 Slice(切片)
Array(数组)
参考:
Array(数组) 是具有相同的唯一类型的一组 已编号、且长度固定 的数据项序列。每个数据项称为 element(元素)、长度指的是元素的个数、编号指每个元素的 index(索引),索引号从 0 开始。
[n]T
用以表示一个数组,该数组包含 n 个 T 类型的值。
Array 的声明
var ArrayID [LENGTH]TYPE
- ArrayID # 标识符(i.e.数组的名字)
- LENGTH # 数组长度(i.e.元素的个数)
- TYPE # 每个元素的数据的类型。
**[ ]**
# 括号是数组类型的标识符,不要忘记写。
比如:var arr [10]int
这定义了一个名为 arr 的数组,这个数组由 10 个 int 类型的数据组成。简化点的口头语,声明了一个长度为 10 的整形数组。
Array 的赋值
arr[0] = "Hello"
为数组的 0 号元素赋值。
Array 的实例化
数组声明后,默认初始化每个元素的值为 0,后续可以对每个元素进行赋值。数组可以有两种初始化方式
- 每次对一个元素进行赋值,一般使用循环来实现
- 使用
{}
大括号,直接对数组进行初始化- e.g.
var arr = [5]int{1,5,23,2,10}
- e.g.
Array 的引用
引用数组的长度
len(MapID)
使用 len()
函数,括号内为数组标识符。数组的长度也就是元素的数目,必须是固定的并且在声明该数组时就给出,数组长度最大为 2Gb。格式为 len(ARRAYS)
len 是 length 的缩写,ARRAYS 是数组变量的名称。
- e.g.对于上面例子中定义的数组,数组的长度为
len(arr)
引用数组中的元素
ArrayID[INDEX]
- ArrayID # 数组标识符
- INDEX # 元素编号
数组的元素可以通过索引(数组的位置,索引有时候也叫作数组中元素的编号)来读取(或修改),索引从 0 开始,第一个元素的索引为 0,第二个索引为 1,以此类推(长度为 3 的数组,元素的索引为 0、1、2)。
- e.g.对于上面例子中定义的数组,第一个元素是
arr[0]
,第二个元素是arr[1]
…..第五个元素是arr[4]
多维数组
数组通常是一维的,但是可以用来组装成多维数组。e.g.[3][5]int
有行有列,[2][2][2]float64
立体效果。代码示例:multidim_array.go
Slice(切片)
Slice(切片) 是一个长度可变的数组,是数组的一部分;是对数组一个连续片段的引用。这个片段可以是整个数组、或是由起始和终止索引标识中间的元素子集,注意:终止索引标识符的元素不包括在切片内。
切片的由来:Go 中的数组是一个值,数组变量表示整个数组,而不是指向数组第一个元素的指针。这就意味,将一个数组当作参数传递时,会完全拷贝数组中的内容(当数组非常大的时候,会非常占用资源,使用起来也不便利),这时候就可以是使用切片来作为参数进行传递。**可以把数组当成一个存储元素的地方,具有索引,有着固定的大小。而切片则是指向这个存储元素地方的指针。**所以 Golang 中一般使用切片来对数组进行引用和传递参数。
注意:绝对不要用指针指向切片。切片本身已经是一个引用类型,所以它本身就是一个指针!
Slice 的声明
var SliceID []TYPE
。MapID 为该切片的名字,[]中括号内不指明长度
Slice 的实例化
var SliceID []TYPE = ARR[START:END]
。切片通过数组 ARR 从 START 号索引到 END-1 号索引之间的元素构成自己(切分数组,START:END
被称为 slice 表达式)。切片的长度为 END-START
,切片的容量为从所引用的数组索引号START这个元素到这个数组最后一个元素的所有元素的个数
- e.g.如果定义了一个数组
var arr1 [7]int
var slice1 []type = arr1[2:5]
。slice1[0]
等于arr1[2]
。len(slice1)
切片长度为 3,cap(slice1)
切片容量为 5var slice2 []type = arr1[:]
切片 slice2 等于完整的 arr1 数组。另一种表示方式:slice2 = &arr1
arr1[2:]
和arr1[2:len(arr1)]
相同,表示包含了数组的 2 号索引到最后最一个索引的所有元素。arr1[:3]
和arr1[0:3]
相同,表示包含了从数组的 0 号索引到 2 号索引的所有元素(不包括 3 号索引的元素)。s := [3]int{1,2,3}[:]
和s := []int{1,2,3}
相同,表示由数字 1、2、3 组成的切片s2 := s[:]
使用切片组成的切片,拥有相同的元素,但是仍然指向相同的相关数组var x = []int{2,3,4,5,11}
创建了一个长度为 5 的数组且创建了一个相关切片。
使用make()
函数来创建一个切片,同时创建好相关数组。
格式:var SliceID []TYPE = make([]TYPE, LEN, CAP)
也可以简写为SliceD := make([]TYPE, LEN, CAP)
(其中 CAP 是可省的,默认与 LEN 相同)。MapID
为切片名;TYPE
为该切片的数据类型;LEN
为该切片的长度;CAP
为该切片的总容量。CAP 可以理解为切片所引用的数组的长度,切片的长度不能超过容量 i.e.不能超过所引用的数组的长度。make()函数接受 2 个参数:元素的类型、切片的个数。
- e.g.
s2 := make([]int, 10)
。定义了一个名为 s2,长度与容量都为 10 的整型切片- 这个例子可以拆解为两句,首先会声明一个数组
var XX [10]int
,然后使用该数组初始化一个切片var s2 []int = XX[:]
Note:使用 make,而不是直接使用var persons []Person
的声明方式。还是有所差别的,使用 make 的方式,当数组切片没有元素的时候,Json 会返回[]。如果直接声明,json 会返回 null
- 这个例子可以拆解为两句,首先会声明一个数组
Slice 的引用
for-range 结构
使用该结构可以对数组或切片中的索引和元素的值进行相关操作,该结构可以返回索引与元素的值
格式:for INDEX,VAL := range SliceID {...}
。
返回值 INDEX 为数组或切片的索引;返回值 VAL 为该索引位置的值;MapID 为该数组或切片的名字代码示例:for-range.go\
Slice 的 reslice(重组)
在使用 make()
函数创建切片的时候,LEN 作为切片的初始长度,而 CAP 作为所切片所相关的数组的长度。这么做的好处是切片在达到 LEN 所定义的上限后,可以扩容,直到扩容到 CAP 定义的容量。改变切片长度的过程称之为切片的重组(reslicinig)。
Slice 的追加 append() 与复制 copy()
append()
格式 1:SLICE2 := append(SLICE1, X1, X2...)
df
把 X1,X2 等元素追加给切片 SLICE1,追加的元素必须和原切片的元素类型相同。如果 SLICE1 的容量不足以存储新增的元素,append 会分配新的切片来保证已有切片元素和新增元素的存储。因此,返回的切片可能已经指向一个不同的相关数组了。append 方法总是返回成功,除非系统内存耗尽了。
append 格式 2:SLICE2 := append(SLICE1, SLICE3)
可以将切片 SLICE3 追加到 SLICE1 的后面
copy 格式:copy(SLICE1, SLICE2)
把切片 2 复制给切片 1
Slice 的删除
参考:
Go 语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素,根据要删除元素的位置有三种情况,分别是从开头位置删除、从中间位置删除和从尾部删除,其中删除切片尾部的元素速度最快。
Go 语言中切片删除元素的本质是:以被删除元素为分界点,将前后两个部分的内存重新连接起来。
Go 语言中切片元素的删除过程并没有提供任何的语法糖或者方法封装,无论是初学者学习,还是实际使用都是极为麻烦的。
连续容器的元素删除无论是在任何语言中,都要将删除点前后的元素移动到新的位置。随着元素的增加,这个过程将会变得极为耗时。因此,当业务需要大量、频繁地从一个切片中删除元素时,如果对性能要求较高,就需要反思是否需要更换其他的容器(如双链表等能快速从删除点删除元素)。
seq := []string{"a", "b", "c", "d", "e"}
// 指定删除位置
index := 2
// 查看删除位置之前的元素和之后的元素
fmt.Println(seq[:index], seq[index+1:])
// 将删除点前后的元素连接起来
seq = append(seq[:index], seq[index+1:]...)
fmt.Println(seq)
代码输出结果: [a b] [d e] [a b d e] 第 1 行,声明一个整型切片,保存含有从 a 到 e 的字符串。 第 4 行,为了演示和讲解方便,使用 index 变量保存需要删除的元素位置。 第 7 行中:seq[:index] 表示的就是被删除元素的前半部分,值为: [1 2] seq[index+1:] 表示的是被删除元素的后半部分,值为: [4 5] 第 10 行使用 append() 函数将两个切片连接起来。 第 12 行,输出连接好的新切片。此时,索引为 2 的元素已经被删除。 代码的删除过程可以使用下图来描述。
排序
参考:
Go 的 sort 包可以对内置的数据类型以及自定义数据类型进行排序。通常都是作用在对应类型的数组、切片中。
反馈
此页是否对你有帮助?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.