在 Go 语言中,为便于存储及管理用户数据,其数据结构设计分为数组 Array、切片 Slice、映射 Map 三种结构。
近期又看了 Go 语言基础的内容,看了一下这三种结构实现的原理:
数组 Array
- 数组是切片和映射的基础数据结构;
- 数组是长度固定的数据类型并且在内存中也是连续分配的,固索引数组数据速度是非常快的;
- 声明数组时需要指定数组存储的类型及数量(数组的长度);
- 数组变量的类型包括数组长度和元素的类型,只有两部分都相同的数组才可相互赋值。
创建及初始化
一旦声明了数组,其本身的数据类型及长度都是不可以进行变更。
|
|
指针类型
数组元素的类型可以为任何内置类型,也可以是某种结构类型,也可以是指针类型。
|
|
多维数组
数组本身是一维数据,多维数组是由多个数组组合而来的。
|
|
在函数间传递数组:由于在函数间传递变量时,传递的总是变量的值的副本,所以在传递数组变量时将拷贝整个数组!在定义函数时,对于较大的数据类型应该把参数设计为指针类型,这样在调用函数时,只需在栈上分配给每个指针8字节的内存,但这意味着会改变指针指向的值(共享的内存),其实大部分情况下应该使用切片类型,而不是数组。
切片 Slice
- 切片 slice 是引用类型,它引用了其指针字段所指向的底层数组的一部分或全部;
- 切片是围绕动态数组的概念构建的;
- 切片的动态增长是通过 append 来实现的;
- 缩小则是通过对它再次切片来实现,通过再次切片获得的新切片将和原切片共享底层数组,它们的指针指向同一个底层数组。
创建及初始化
切片类型有3个字段:
- 指针:指向切片所包含的第一个元素在底层数组中的地址;
- 长度:切片所包含的底层数组的元素的个数(切片可访问的元素的个数);
- 容量:切片允许增长到的最大元素个数,即底层数组的长度。
make 和切片字面量
|
|
nil 和空切片
|
|
由于切片只是引用了底层数组,底层数组的数据并不属于切片本身,所以一个切片只需要 24字节的内存(在 64位机器上):指针字段 8字节、长度字段 8字节、容量字段 8字节。所以在函数之间直接传递切片是高效的,只需分配 24字节的栈内存。
len
函数可返还切片的长度、cap
函数可返还切片的容量。
映射 Map
- 映射 map 是用来存储一系列的无序键值对;
- 映射是无序的集合,其实现使用了散列表;
- 映射的散列表包含一组桶,每个桶里存储着一部分键值对;
- 映射内部使用了两个数组:
- 第一个数组:存储着用于选择桶的散列键的高八位值,该数组用于区分每个键值对要存在哪个桶里;
- 第二个数组:每个桶里都有一个字节数组,先依次存储了该桶里的所有键,之后存储了该桶的所有值;
创建及初始化
|
|
遍历映射的键值对时的顺序是随机,若要有序的获得映射的键值对,则需要先遍历出映射的键存到一个切片中,然后排序该切片,最后遍历该切片,按切片中元素的顺序去映射中取对应的值。