golang中的数组

1,数组的特性

数组是线性表结构,从而内存空间是连续的且有着相同类型的数据。

正是由于是线性结构的特性才支持随机访问,时间复杂度为o(1)。

通过公式a[i]_address = base_address + i * data_type_size计算得到数组元素地址。

但是其插入、删除操作比较低效,因为会涉及到数据的迁移问题。以上就是数组的基本特性,下面我们看一下golang中数组相关知识。

2,声明及初始化

2.1,直接声明不显示初始化

var arr []type

数组声明之后编译器会做初始化操作,用数组值类型的零值进行初始化。

2.2,用一组值初始化数组

var arr [3]type = []type{1, 2, 3}

2.3,在数组字面值中,如果在数组的长度位置出现的是“...”省略号,则表示数组的长度是根据初始值的长度确定的。

q := [...]int{1, 2, 3}

2.4,制定索引和对应值列表的方式初始化

type Color int  const (  YELLOW = iota  RED  GREEN  BLUE  )  symbol := [...]string{YELLOW: "#FFFF00", RED: "#FF0000", GREEN: "#008000", BLUE: "#0000FF"}

2.5,定义数组大于0的索引初始化,其它元素都是用0自动初始化。

r := [...]int{99: -1}

此r数组的元素值是99个0,最后一位是-1

3,数组比较

如果一个数组的元素类型是可以相互比较的,那么数组类型也是可以相互比较的,这时候我们可以直接通过==比较运算符来比较两个数组,只有当两个 数组的所有元素都是相等的时候 数组才是相等的。

数组长度是数组类型的组成部分,[1]int与[2]int是2种不同的数组类型。

数组长度必须是常量表达式,因为数组的长度需要在编译阶段确定。

4,数组越界

  • 数组的长度是固定的,不能访问数组下标合法范围之外的值。
  • 访问非法下标则触发访问越界,会panic。

5,类型、容量、长度

  • 数组是值类型,顾名思义就是数组里面的数据不是数组地址。
  • 数组的长度可以通过len(arr)来获取到。
  • 数组的容量可以通过cap(arr)来获取到。

6,打印

fmt.Printf("%p", &arr) 打印数组首地址。
fmt.Printf("%p", &arr[1])打印数组非首地址。

7,函数参数为数组

一般函数的参数传递很少用到数组传参,因为数组传参是值传递,需要拷贝整个数组,需要更改数组中的值需要传数组地址。

8,数组的内存布局

由于数组是连续的内存空间,为了直观的感受一下我把数组内存地址指向的数据打印出来。注意由于是int是占4个字节,我的系统是64位所以int数组低4位存储值且不足的字节用0填充,而高4位的0的目的是字节对齐。见下图1,图2:

图1

图2

9,数组遍历

  • 通过range进行循环遍历。
  • 通过len(arr) + for循环遍历。

10,数组指针

  • 只的是数组元素可以是指针类型,例如:
arr := [3]*int{new(int), new(int)}

11,二维数组

package main

import "fmt"

var arr = [4][2]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}}

func main()  {
    fmt.Println(arr[2][1])
}

以上代码声明了4行2列的数组,数组元素的访问是通过数组的下标来实现的。那数组的元素在真实内存中是按什么顺序排列的呢,看下图3:

图3

我们可以看到数组的值排序是将行依次拼接而成。

12,总结

数组是golang中比较基本的数据类型,做为一个容器来为slice提供存储服务,但是在实际应用中直接用它不是很多,用slice则用的很多因为它灵活。下篇讲解golang中slice的使用。

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章