Go 语言笔记 - 数组

有经验的程序员都知道,实际项目中很难遇到不需要存储和读取集合数据的情况。不论是读写数据库或文件,或者访问网络,都需要有一种方式来处理接收和发送的数据。

Go 语言中有 3 种数据结构可以让用户管理集合数据:数组、切片(slice)和映射(map)。数组是切片和映射的基础数据结构

数组

  • 数组创建后占用一块连续的内存
  • 通过索引(也称下标)访问数组元素
  • 数组声明后长度和值的类型就无法修改

语法

  1. 创建数组
// 声明格式 var 变量名 [长度]类型
var arr1 [5]int // 初始化为 [0,0,0,0,0]
var arr2 = [...]int{1, 2, 3} // 初始化为 [1, 2, 3]
arr3 := [5]int{1,2,3,4,5} // 初始化为 [1, 2, 3, 4, 5]
  1. 修改数组元素
    通过索引下标获取和修改数组元素
arr1[0] = 1 // arr1 [1, 0, 0, 0, 0]
arr1[4] = 5 // arr1 [1, 0, 0, 0, 5]
arr1[5] = 6 // invalid array index 5 (out of bounds for 5-element array)
  1. 获取长度和容量
    数组在初始化时,会指定长度,这个值可以通过 len() 函数获得。数组容量可以通过 cap() 函数获得。数组创建后长度和容量是一致的。
len(arr1)  
cap(arr1)

4.遍历
使用 forrange 遍历数组

arr := [5]int{1,2,3,4,5}
for index, value := range arr {
    fmt.Println("index: ", index, " value: ", value)
}

数组的内部实现

在 Go 语言里,数组是一个长度固定的数据类型,用于存储一段具有相同类型的元素的连续块。数组存储的类型可以是内置类型,如整型或字符串,也可以是某种结构类型。

在图 1-1 中可以看到数组的表示。灰色格子代表数组里的元素,每个元素都是紧邻另一个元素,每个元素包含相同的类型,这个例子里是整数,并且每个元素拥有一个唯一的索引(也称下标)来访问。

图 1-1 数组的存储结构

数组是一个长度固定的数据类型,因为其占用的内存是连续分配的,CPU 能把正在使用的数据缓存更长时间。而且内存连续很容易计算索引,可以快速迭代数组里的所有元素。数组的类型信息可以提供每次访问一个元素时需要在内存中移动的距离。既然数组的每个元素类型相同,又是连续分配,就可以以固定速度索引数组中的任意数据,速度非常快。

总结

数组的特点:

  • 数组创建后占用一块连续的内存
  • 通过索引(也称下标)访问数组元素
  • 数组声明后长度和值的类型就无法修改

内存连续的好处:

  • CPU 能把正在使用的数据缓存更长时间
  • 容易计算索引
  • 快速迭代数组里的所有元素

类型固定的好处:

  • 每次访问一个元素时在内存中移动的距离固定

推论:内存连续分配,又类型固定,就可以以固定的速度索引数组中的任意数据,速度非常快。

在函数间传递数组

根据内存和性能来看,在函数间传递数组是一个开销很大的操作。在函数之间传递变量时,总是以值的方式传递的。如果这个变量是一个数组,意味着整个数组都会被完整赋值,并传递给函数。
为了验证这个操作,我们来创建一个包含 100 万个 int 类型元素的数组。在 64 位架构的机器上,这需要 800 万字节,即 8 MB 的内存。

var array [1e6]int

func main() {
    foo(array)
}

func foo(array [1e6]int) {
    fmt.Println("array length: ", len(array))
}

每次函数 foo 被调用时,都要在栈上分配 8MB 的内存。之后,整个数组的值(8MB的内存)被复制到刚分配的内存里。因此这个操作的代价是随着数组的长度而变大。我们可以通过传入数组的指针的方式来处理这个操作。这样只需要复制 8 字节数据而不是 8 MB 的数据到栈上。

var array [1e6]int

func main() {
    foo(&array)
}

func foo(array *[1e6]int) {
    fmt.Println("array length: ", len(array))
}

这个操作会更有效地利用内存,性能也更好。不过因为现在传递的是指针,所以如果改变指针指向的值,会改变共享的内存。使用切片能更好地处理这类共享问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容

  • 来源:NumPy Tutorial - TutorialsPoint 译者:飞龙 协议:CC BY-NC-SA 4...
    布客飞龙阅读 32,811评论 6 97
  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,694评论 24 1,002
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,519评论 1 51
  • 现在大家都在讨论怎么挣钱,钱是多么难挣等等问题,归根结底本质问题就一点: 1.没钱的普通人怎么挣钱?在这里没钱的普...
    徐家小球阅读 362评论 0 0
  • 六月的长沙,不似往年的干燥炎热,匆匆充斥的是中考、高考云云,在我们大学生一众中,大多牵涉的便是今年暑假的长短了。 ...
    市就阅读 279评论 0 0