数组是由固定长度的特定类型元素组成的序列,数组可以由零个或多个元素组成(默认情况下,数组的每个元素都被初始化为元素类型对应的零值),数组的长度是固定的,因此在Go语言中很少直接使用数组。和数组对应的类型是 Slice(切片),它是可以增长和收缩的动态序列,slice 功能也更灵活,但是要理解 slice 工作原理的话需要先理解数组。
创建数组#
// 数组创建,使用类型零值初始化
func createArrayDeclar() {
var arr [3]int // array of 3 integers
fmt.Println(arr[0]) // print the first element
fmt.Println(arr[len(arr)-1]) // print the last element, a[2]
}数组字面值#
// 数组创建,使用数字字面值语法
func createArrayDeclar2() {
var arr [3]int = [3]int{1, 2, 3}
fmt.Println(arr[0])
// fmt.Println(a[10]) invalid array index 10 (out of bounds for 3-element array),数组越界
}数组字面值中,如果数组的长度位置出现的是…省略号,表示数组的长度根据初始化值的个数来计算。
func createArrayDeclar3() {
arr := [...]int{1, 2, 3}
fmt.Println(arr[0])
}指定数组第1个元素值为100,第9个元素值为200,数组长度就是10
func createArrayDeclar4() {
arr := [...]int{1: 100, 9: 200}
fmt.Println(arr)
}数组比较#
数组可以直接进行比较,当数组内的元素都一样的时候表示两个数组相等。
q := [...]int{11, 22, 33}
w := [...]int{11, 22, 33}
fmt.Println(q == w)数组遍历#
func traversalArray() {
var arr [3]int = [3]int{1, 2, 3}
for i := 0; i < len(arr); i++ {
fmt.Printf("index:%d, value:%d\n", i, arr[i])
}
// 使用range遍历数组
for i, v := range arr {
fmt.Printf("index:%d, value:%d\n", i, v)
}
// 使用range遍历数组:如果需要值但希望忽略索引,可以通过使用_ blank标识符替换索引来实现
for _, v := range arr {
fmt.Printf("value:%d\n", v)
}
}多维数组#
func multidimensionalArray() {
array := [3][4]int{
{0, 1, 2, 3}, /* 第一行索引为 0 */
{4, 5, 6, 7}, /* 第二行索引为 1 */
{8, 9, 10, 11}, /* 第三行索引为 2 */
}
for i, item := range array {
fmt.Printf("%d the element of is %v \n", i, item)
}
}0 the element of is [0 1 2 3]
1 the element of is [4 5 6 7]
2 the element of is [8 9 10 11]数组作为参数传递#
数组可以作为函数的参数传入,数组作为函数参数传入用的是值传递的方式(拷贝)。在函数内改变数组元素并不影响外层数组。
func passByValue(arr [3]int) {
arr[0] = 1
} // 数组是值类型:意味着当它被分配给一个新变量时,将把原始数组的副本分配给新变量。如果对新变量进行了更改不会在原始数组中反映
e := [...]int{11, 22, 33}
fmt.Println(e[0])
passByValue(e)
fmt.Println(e[0])输出:
11
11如果想要改变就只能使用指针,在函数内部改变的数组的值,也会改变外面的数组的值。
func passByReference(arr *[3]int) {
arr[0] = 100
} // 使用指针后函数内部对数组的更改将反应到原数组上
r := [...]int{11, 22, 33}
fmt.Println(r[0])
passByReference(&r)
fmt.Println(r[0])输出:
11
100这里只是玩一下,正常这种情况下都是用切片来解决,而不是用数组。
这里的 * 和 & 的区别:
&是取地址符号 , 即取得某个变量的地址 , 如 ;&a*是指针运算符 , 可以表示一个变量是指针类型 , 也可以表示一个指针变量所指向的存储单元 , 也就是这个地址所存储的值
Slice (切片)代表变长的序列,序列中每个元素都有相同的类型。一个 slice 类型一般写作 []T ,其中 T 代表 slice 中元素的类型;slice 的语法和数组很像,只是没有固定长度而已。
slice 的底层引用一个数组对象。一个 slice 由三个部分构成:指针、长度和容量。指针指向第一个 slice 元素对应的底层数组元素的地址,要注意的是 slice 的第一个元素并不一定就是数组的第一个元素。长度对应slice 中元素的数目;长度不能超过容量,容量一般是从 slice 的开始位置到底层数据的结尾位置。内置的 len 和 cap 函数分别返回 slice的长度和容量。多个 slice 之间可以共享底层的数据,并且引用的数组部分区间可能重叠。