1.内部实现

在Go语言里,数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素的连续块。

数组存储的类型可以是内置类型,如整型或字符串,也可以是某种结构类型。

灰格子代表数组里面的元素,每个元素都紧邻另一个元素。

每个元素都属于相同的类型,并且每个元素可以用一个唯一的索引(也称下标或标号)来访问。

数组是一种非常有用的数据结构,因为其占用的内存是连续分配的。

由于内存连续,CPU能把正在使用的数据缓存更久的时间。

而且内存连续很容易计算索引,可以快速迭代数组里的所有元素。

数组的类型信息可以提供每次访问一个元素时需要在内存中移动的距离。

既然数组的每个元素类型相同,又是连续分配,就可以以固定速度索引数组中的任意数据,速度非常快。

2.声明和初始化

声明数组时需要指定内部存储的数据类型,以及需要存储的元素的数量,这个数量也称为数组的长度。

(1)声明一个数组,并设置为零值

  1. //声明一个包含5个元素的整型数组
  2. var array [5]int

一旦声明,数组里存储的数据类型和长度就都不能改变了。

如果需要存储更多的元素,就需要先创建一个更长的数据,再把原来数组里的值复制到新数组里。

在Go语言中声明变量时,总会使用对应类型的零值来对变量进行初始化。数组也不例外。

当数组初始化时,数组内每个元素都初始化为对应类型的零值。

整型数组里的每个元素都初始化为0,也就是整数的零值。

(2)使用数组字面量声明数组

一种快速创建数组并初始化的方式是使用数组字面量。

数组字面量允许声明数组里元素的数量同时指定为每个元素的值。

  1. //声明一个包含5个元素的整型数组
  2. //用具体值初始化每个元素
  3. array := [5]int{10,20,30,40,50}

(3)让Go自动计算声明数组的长度

如果使用...代替数组的长度,Go语言会根据初始化时数组元素的数量来确定该数组的长度。

  1. //声明一个整型数组
  2. //用具体值初始化每个元素
  3. //容量由初始化值的数量决定
  4. array := [...]int{1020304050}

(4)声明数组并指定特定元素的值

如果知道数组的长度,而且准备给每个值都指定具体值,就可以通过索引来进行指定。

  1. //声明一个有5个元素的数组
  2. //用具体值初始化索引为1和2的元素
  3. //其余元素保持零值
  4. array := [5]int{1:20, 2: 30}

3.使用数组

(1)访问数组元素

因为内存布局是连续的,所以数组是效率很高的数据结构。

在访问数组里任意元素的时候,这种高效都是数组的优势。

要访问数组里某个单独元素,使用[]运算符。

  1. //声明一个包含5个元素的整型数组
  2. //用具体值初始为每个元素
  3. array := [5]int{10,20,30,40,50}
  4.  
  5. //修改索引为2的元素的值
  6. array[2] = 35

(2)访问指针数组的元素

声明一个所有元素都是指针的数组。使用*运算符就可以访问元素指针所指向的值

  1. //声明包含5个元素的指向整数的数组
  2. //用整型指针初始化索引为0和1的数组元素
  3. array := [5]*int(0: new(int), 1: new(int))
  4.  
  5. //为索引为0和1的元素赋值
  6. *array[0] = 10
  7. *array[1] = 20

(3)把同样类型的一个数组赋值给另外一个数组

在Go语言里,数组是一个值。这意味着数组可以用在赋值操作中。

变量名代表整个数组,因此,同样类型的数组可以赋值给另一个数组。

  1. //声明第一个包含5个元素的字符串数组
  2. var array1 [5]string
  3.  
  4. //声明第二个包含5个元素的字符串数组
  5. //用颜色初始化数组
  6. array2 := [5]string{"red", "yellow", "blue", "green", "pink"}
  7.  
  8. //把array2的值赋值给array1
  9. array1 = array2

(4)编译器会阻止类型不同的数组互相赋值

数组变量的类型包括数组长度和每个元素的类型。

只有这两部分都相同的数组,才是类型相同的数组,才能相互赋值。

  1. //声明第一个包含4个元素的字符串数组
  2. var array1 [4]string
  3.  
  4. //声明第二个包含5个元素的字符串数组
  5. //初始化数组
  6. array2 := [5]string{"red", "blue", "yellow", "green", "pink"}
  7.  
  8. //复制
  9. array1 = array2 //cannot use array2 (type [5]string) as type [4]string in assignment

(5)把一个指针数组赋值给另一个

复制指针数组,只会复制指针的值,而不会复制指针所指向的值。

  1. //声明第一个包含3个元素的指向字符串的指针数组
  2. var array1 [3]*string
  3.  
  4. //声明第二个包含3个元素的指向字符串的指针数组
  5. //使用字符串指针初始化这个数组
  6. array2 := [3]*string{new(string), new(string), new(string)}
  7.  
  8. //*array[]表示反取元素的值
  9. //赋值
  10. *array2[0] = "blue"
  11. *array2[1] = "pink"
  12. *array2[2] = "yellow"
  13.  
  14. //复制
  15. array1 = array2

  

4.多维数组

数组本身只有一个维度,不过可以组合多个数组创建多维数组。

多维数组很容器管理具有父子关系的数据或者与坐标系相关联的数据。

(1)声明二维数组

  1. //声明一个二维整型数组,两个维度分别存储4个元素和2个元素
  2. var array [4][2]int
  3.  
  4. //使用数组字面量来声明并初始化一个二维整型数组
  5. array := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}
  6.  
  7. //声明并初始化外层索引为1和2的元素
  8. array := [4][2]int{1: {20, 21}, 2: {30, 31}}
  9.  
  10. //声明并初始化外层数组和内层数组的单个元素
  11. array := [4][2]int{1: {0: 20}, 2: {1: 31}}

(2)访问二维数组的元素

为了访问单个元素,需要反复组合使用[]操作符。

  1. //声明一个2X2的二维整型数组
  2. var array [2][2]int
  3.  
  4. //设置每个元素的整型值
  5. array[0][0] = 10
  6. array[0][1] = 20
  7. array[1][0] = 30
  8. array[1][1] = 40

(3)同样类型的多维数组赋值

只要类型一致就可以将多维数组相互赋值。

多维数组的类型包括每一维度的长度以及最终存储在元素中的数据类型。

  1. //声明两个不同的二维整型数组
  2. var array1 [2][2]int
  3. var array2 [2][2]int
  4.  
  5. //设置每个元素的整型值
  6. array2[0][0] = 10
  7. array2[0][1] = 20
  8. array2[1][0] = 30
  9. array2[1][1] = 40
  10.  
  11. //复制
  12. array1 =array2

(4)使用索引为多维数组赋值

  1. //将array1的索引为1的维度复制到一个同类型的新数组里面
  2. var array3 [2]int = array1[1]
  3.  
  4. //将外层数组的索引为1、内层数组的索引为0的整型值赋值到新的整型变量里
  5. var value int = array1[1][0]

  

5.在函数间传递数组

根据内存和性能来看,在函数间传递数组是一个开销很多的操作。

在函数之间传递变量时,总是以值的变量传递。

如果这个变量是一个数组,意味着整个数组不管有多长,都会完整复制,并传递给函数。

假设现在我们有一个包含100万个int类型元素的数组。

在64位架构上,需要800万字节,也就是8MB内存。

(1)使用值传递在函数间传递大数组

  1. //声明一个需要8MB的数组
  2. var array [1000000]int
  3.  
  4. //将数组传递给foo函数
  5. foo(array)
  6.  
  7. //函数foo接受一个100万个整型的数组
  8. func foo(array [1000000]int) {
  9. ...
  10. }

每次函数foo被调用时,必须在栈上分配8MB的内存。

之后整个数组的值被复制到刚刚分配的内存里。

虽然Go的垃圾回收机制还不错,但是如果大规模调用,势必会有很多资源消耗。

其实我们只需要传递指针,这样只需要8字节的内存分配给指针就可以了。

(2)使用指针在函数间传递大数组

  1. //声明一个需要8MB的数组
  2. var array [1000000]int
  3.  
  4. //将数组传递给foo函数
  5. foo(&array)
  6.  
  7. //函数foo接受一个100万个整型的数组
  8. func foo(array *[1000000]int) {
  9. ...
  10. }

  

go——数组(二)的更多相关文章

  1. hiho一下121周 后缀数组二·重复旋律2

    后缀数组二·重复旋律2 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi ...

  2. Java基本语法-----java数组(一维数组二维数组)

    嘿嘿!你们懂的,又是图片,委屈大家了. java数组(一维数组二维数组) [正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!下面有个"顶"字,你就 ...

  3. C++学习(十五)(C语言部分)之 数组二

    数组大纲 多维数组 二维数组 重点 (三位以上基本不会用到) 都是用来存数据 一个班有20个人 可以用一维数组存20个人的年龄 int age[20]; 一个年级10个班 每个班20人 int age ...

  4. javascript数据结构和算法 第二章 (数组) 二

    字符串表示的数组 join() 和 toString() 函数返回数组的字符串表示.这两个函数通过将数组中的元素用逗号分隔符切割,返回字符串数组表示. 这里有个样例: var names = [&qu ...

  5. hihocoder #1407 : 后缀数组二·重复旋律2

    #1407 : 后缀数组二·重复旋律2 Time Limit:5000ms Case Time Limit:1000ms Memory Limit:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢 ...

  6. 数据结构 二维数组-->稀疏数组-->二维数组

    稀疏数组基本概念: 稀疏数组应用场景: 当一个数组大部分的元素为"0",或者为同一个值的数组时,可以使用稀疏数组来保存该数组 处理方法: 1>记录数组一共有几行几列,有多少不 ...

  7. Java 一维数组 二维数组 三维数组

    二维数组包含一位数组  三维数组就是在二维数组的基础上,再加一层.把二维数组看做是一维数组就可以了,按照上述理解类推.   下面是 一维 二维 三维数组例子   一维数组: int[] array1 ...

  8. java 获取数组(二维数组)长度实例程序

    我们可能知道 js有个length函数,java也有啊length函数 例 如果数组是data[],则data.length 代码如下 复制代码 byte[] phone =new byte[81]; ...

  9. 【转】C++动态创建二维数组,二维数组指针

    原作者博客:蒋国宝的IT技术博客 今天完成一道题目需要自己用指针创建一个二维的数组,不得不承认指针的确是恶心. int **result; ; ; result = new int*[row]; ; ...

  10. php php打乱数组二维数组、多维数组

    php中的shuffle函数只能打乱一维数组,有什么办法快速便捷的打乱多维数组?手册上提供了 <?php function shuffle_assoc($list) {      if (!is ...

随机推荐

  1. 怎么来爬取代理服务器ip地址?

    一年前突然有个灵感,想搞个强大的网盘搜索引擎,但由于大学本科学习软件工程偏嵌入式方向,web方面的能力有点弱,不会jsp,不懂html,好久没有玩过sql,但就是趁着年轻人的这股不妥协的劲儿,硬是把以 ...

  2. Centos6.X 安装MongoDb

    1.查看linux版本,之所以查看linux版本,是因为centos7和以前版本用的防火墙不一样,安装完mongodb后,需要关闭防火墙(或者其他方法,专业运维人员使用,我们这里为简单,直接关闭即可) ...

  3. chpasswd 更简单的更改密码的方式

    [root@m01 .ssh]# useradd test[root@m01 .ssh]# echo "test:123"|chpasswd Linux命令:chpasswd 批量 ...

  4. java基础-集合笔记

    Iterator(foreach) 遍历时只能通过iterator去删除(添加)元素,不能直接通过集合对象删除或添加元素 Set HashSet底层是一个HashMap HashSet添加元素,先判断 ...

  5. 好久没写blog了 ~ 换了个城市,换了个公司,各种忙碌

    最近一直在忙工作交接以及换城市.入职的事情 ~~~ 新公司做C++的比较少,so全上C++11了,写代码各种爽. 最近应该会写一点关于QT的blog , 学到新知识了哈.

  6. SQLServer中Partition By

    http://www.cnblogs.com/vincentonline/p/4999225.html 今天群里看到一个问题,在这里概述下:查询出不同分类下的最新记录.一看这不是很简单的么,要分类那就 ...

  7. 使用ghost硬盘对拷备份系统

    公司有台server装了OA系统.要备份数据.同一时候假设系统出错之后可以及时回复.所以有买了块同型号硬盘. 用ghost的硬盘对拷功能,将原硬盘的系统和数据拷到新硬盘上.新硬盘挂到server上.当 ...

  8. hdu3625(第一类斯特林数)

    与第二类有些区别! #include <stdio.h> #include <stdlib.h> #include <string.h> #include < ...

  9. java汉字转拼音的工具类

    import com.google.common.base.Strings;import net.sourceforge.pinyin4j.PinyinHelper;import net.source ...

  10. Eclipse项目推送至github

    0. 安装好git,配置正确 网上教程很多,略 1. 将eclipse中的项目放入git本地库 1.右键项目-->Team-->Share Project 2.勾选 Use or crea ...