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的使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容