数组
如何定义数组
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。
数组声明
Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:
var variable_name [SIZE] variable_type
以上为一维数组的定义方式。例如以下定义了数组 balance
长度为 10 类型为 float32:
var balance [10] float32
数组初始化
var balance = [5]float32{1000.0,2.0,3.4,7.0,50.0}
初始化数组中 {} 中的元素个数不能大于 [] 中的数字。
如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
如何操作数据
可以通过循环的方式为其赋予初值:
for i := 0; i < len(arr1); i++ {
arr1[i] = i * 10
}
可以通过循环的方式遍历数组,与上面不同的是,for循环提供这样的方式来为便利数组:
for index, value := range arr1 {
fmt.Printf("index: %d, value: %d\n", index, value)
}
多维数组
Go 语言支持多维数组,以下为常用的多维数组声明方式:
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
实例:
var arr4 = [5][5]int{
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
}
输出数组得:
[[1 2 3 4 5] [6 7 8 9 10] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
数组作为函数参数
go语言在传递数组时会对其进行拷贝,所以如果传递的是大数组的话会非常占内存,所以一般情况下很少直接传递一个数组,避免这种情况我们可以使用以下两种方式:
- 传递数组的指针
- 传递切片
指针数组与数组指针
对于指针数组和数组指针在c或c++中也经常被讨论,尤其对于初学者来说会分辨不清楚。其实在每个词中间添加一个“的“就很好理解了,指针的数组,数组的指针。
指针数组
一个数组里面装的都是指针,在go语言中数组默认是值传递的,所以如果我们在函数中修改传递过来的数组对原来的数组是没有影响的。
func main() {
var a [5]int
fmt.Println(a)
test(a)
fmt.Println(a)
}
func test(a [5]int) {
a[1] = 2
fmt.Println(a)
}
输出结果为:
[0 0 0 0 0]
[0 2 0 0 0]
[0 0 0 0 0]
数组指针
了解了指针数组之后,再来看一下数组指针,数组指针的全称应该叫做,指向数组的指针,在go语言中我们可以如下操作:
func main() {
var a [5]int
var aPtr *[5]int
aPtr = &a
//这样简短定义也可以aPtr := &a
fmt.Println(aPtr)
test(aPtr)
fmt.Println(aPtr)
}
func test(aPtr *[5]int) {
aPtr[1] = 5
fmt.Println(aPtr)
}
输出结果为:
&[0 0 0 0 0]
&[0 5 0 0 0]
&[0 5 0 0 0]
切片
Go 语言切片是对数组的抽象。因为数组是固定长度的,所以在一些场合下就显得不够灵活,所以go语言提供了一种更为便捷的数据类型叫做切片。切片操作与数组类似,但是它的长度是不固定的,可以追加元素,如果以达到当前切片容量的上限会再自动扩容。
如何定义切片
可以声明一个未指定大小的数组来定义切片:
var identifier []type
切片不需要说明长度。
使用make()
函数来创建切片:
var slice1 []type = make([]type, len)
也可以简写为
slice1 := make([]type, len)
也可以指定容量,其中capacity
为可选参数:
make([]T, length, capacity)
这里len是数组的长度并且也是切片的初始长度。
可以通过len()
和cap()
这两个函数来获取切片的长度和容量,下面就来依次看下上面各切片的长度以及容量。
s1 [] 0 0
s2 [1 2 3] 3 3
s3 [0 0 0 0 0] 5 5
s4 [0 0 0 0 0] 5 10
如果我们通过这种方式定义一个切片,那么他会被赋予切片的空值nil。
var s5 []int
切片操作
我们可以通过如下的方式在数组和切片上继续获取切片:
func main() {
arr := [5]int{1, 2, 3, 4, 5}
s := []int{6, 7, 8, 9, 10}
s1 := arr[2:4]
s2 := arr[:3]
s3 := arr[2:]
s4 := s[1:3]
fmt.Println("s1:", s1)
fmt.Println("s2:", s2)
fmt.Println("s3:", s3)
fmt.Println("s4:", s4)
}
输出结果为:
s1: [3 4]
s2: [1 2 3]
s3: [3 4 5]
s4: [7 8]
可以看到切片操作是“包左不包右”,例如arr[2:4]是选择arr数组内下标为2,3的两个元素。如果:左边没有起始位置则默认从头开始,同理如果右边没有终止位置则默认到末尾。
切片的扩充和拼接
对切片进行扩充:
func main() {
a := []int{1, 2, 3}
b := a[1:3]
b = append(b, 4)
b = append(b, 5)
b = append(b, 6)
b = append(b, 7)
fmt.Println(a)
fmt.Println(b)
}
输出结果为:
[1 2 3]
[2 3 4 5 6 7]
如果想要将两个切片进行拼接可以使用如下这种方式:
func main() {
a := []int{1, 2, 3}
b := a[1:3]
fmt.Println(b)
a = append(a, b...)
fmt.Println(a)
}
如果我们想要将一个切片的值复制给另一个切片,go语言也提供了非常简便的方式:
func main() {
a := []int{1, 2, 3}
b := make([]int, 3)
copy(b, a)
fmt.Println(a)
fmt.Println(b)
}
参考:
DatawhaleChina
菜鸟教程