数组

在复合数据类型中数组是由同构的元素组成——每个数组元素都是完全相同的类型——结构体则是由异构的元素组成的。数组和结构体都是有固定内存大小的数据结构。相比之下,slice和map则是动态的数据结构,它们将根据需要动态增长。

数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。由于数组的长度是固定的,因而在使用的时候我们用的最多的是slice(切片),它是可以增长和收缩动态序列,slice功能也更灵活,但是要理解slice工作原理的话需要先理解数组。

数组的每个元素可以通过索引下标来访问,索引下标的范围是从0开始到数组长度减1的位置。内置的len函数将返回数组中元素的个数。

数组的每个元素都被初始化为元素类型对应的零值,对于数字类型来说就是0。

  1. var m [3]int = [3]int{1, 2, 3}
  2. var n [3]int = [3]int{1, 2}
  3. fmt.Println(n[2]) // "0"

在数组字面值中,如果在数组的长度位置出现的是“…”省略号,则表示数组的长度是根据初始化值的 个数来计算。

  1. m := [...]int{1, 2, 3}
  2. fmt.Printf("%T\n", m) // "[3]int"

数组的长度是数组类型的一个组成部分,因此[3]int和[4]int是两种不同的数组类型。数组的长度必须是常量表达式,因为数组的长度需要在编译阶段确定。

数组可以直接进行比较,当数组内的元素都一样的时候表示两个数组相等。

  1. arr1 := [3]int{1, 2, 3}
  2. arr2 := [3]int{1, 2, 3}
  3. arr3 := [3]int{1, 2, 4}
  4. fmt.Println(arr1 == arr2, arr1 == arr3) //true,false

数组可以作为函数的参数传入,但由于数组在作为参数的时候,其实是进行了拷贝,这样在函数内部改变数组的值,是不影响到外面的数组的值得。

  1. func ArrIsArgs(arr [4]int) {
  2. arr[0] = 120
  3. }
  4. m := [...]int{1, 2, 3, 4}
  5. ArrIsArgs(m)

如果想要改变就只能使用指针,在函数内部改变的数组的值,也会改变外面的数组的值:

  1. func ArrIsArgs(arr *[4]int) {
  2. arr[0] = 20
  3. }
  4. m:= [...]int{1, 2, 3, 4}
  5. ArrIsArgs(&m)

通常这样的情况下都是用切片来解决,而不是用数组。

这里的* 和&的区别:

  • & 是取地址符号 , 即取得某个变量的地址 , 如 ; &a
  • *是指针运算符 , 可以表示一个变量是指针类型 , 也可以表示一个指针变量所指向的存储单元 , 也就是这个地址所存储的值.