数组是具有相同唯一类型的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类型例如整形、字符串或者自定义类型(结构体、接口)。数组长度必须是一个常量表达式,并且必须是一个非负整数,数组下标是从0开始的,并且数组的长度是固定不可变的,数组中元素的地址是连续的。数组长度也是数组类型的一部分,所以[5]int和[10]int是属于不同类型的。

在其它编程语言中,数组一般都是引用类型,而在Go语言中,数组属于值类型。

注意:如果我们想让数组元素类型为任意类型的话可以使用空接口作为类型。当使用值时我们必须先做一个类型判断。

声明数组

Go语言数组声明需要指定元素类型及元素个数,语法格式如下:

  1. // 变量名 [大小]类型
  2. var variable_name [len]variable_type

示例:

定义一个长度为5的数组arr

  1. var arr [5]int

以上我们声明了一个数组arr,但是我们还没有对他进行初始化,但是声明的变量都会有默认值,int类型的变量默认值是0,所以arr数组中的每个元素的值都是0。

Go语言中的数组是一种值类型,所以可以通过 new() 来创建: var arr1 = new([5]int) 。那么这种方式和 var arr2 [5]int 的区别是什么呢?arr1 的类型是 *[5]int ,而 arr2的类型是 [5]int

数组在内存的结构

假如我们声明一个长度为5的数组var arr [5]int,我们来看看这个数组在内存中的结构是怎么样的。

上图就是一个Go语言数组在内存的结构,在这个arr数组中,由于我们声明的是int32类型,所以数组中的每个元素在内存中占用的字节数是32/8=4字节,通过arr数组每个元素16进制地址我们可以发现,数组中后一个元素的地址比前一个元素的地址大4个字节,这个4字节正好是int32类型元素占用的内存大小,由此我们也能得出结论:数组中元素的内存地址是连续的;当声明数组时所有的元素都会被自动初始化为数组类型的默认值(int类型的默认值是0,所以arr中每个元素的默认值都是0);数组的下标识从0开始的。数组arr的地址就是数组第一个元素(下标为0的元素)的地址,通过下图打印arr的地址和arr[0]的地址就可以证明

初始化数组

刚刚声明的数组已经被默认的元素类型零值初始化了,如果我们再次进行初始化怎么做呢,可以采用如下办法:

  1. var arr [5]int
  2. arr = [5]int{1, 2, 3, 4, 5}

Go语言提供了声明加初始化的:=操作符,以让我们在创建数组的时候直接初始化。

  1. arr := [5]int{1, 2, 3, 4, 5}

这种简短变量声明的方式不仅适用于数组,还适用于任何数据类型,这也是Go语言中常用的方式。

我们也可以在定义数组是不明确指定长度,让编译器自动推导出长度,可以使用...来替代具体的长度

  1. arr := [...]int{1, 2, 3, 4, 5}

如果我们只想给数组的部分元素指定值,其他元素采用默认值我们可以采用下面的办法

  1. arr := [5]int{0:3, 4:6}

这种方式表示我们只给数组下标为0的元素赋值为3,下标为4的元素赋值为6,其它元素的值依然是该类型的默认值(int的默认值是0)。

使用数组

数组元素的访问非常简单,通过索引(下标)即可访问数组的元素。

  1. arr := [5]int{1, 2, 3, 4, 5}
  2. fmt.Println(arr[0], arr[1], arr[2], arr[3], arr[4])

修改数组的某个元素也很简单:

  1. arr := [5]int{1, 2, 3, 4, 5}
  2. fmt.Println(arr[0])
  3. arr[0] = 66
  4. fmt.Println(arr[0])

如果我们要循环打印数组中的所有值,一个传统的就是常用的for循环:

  1. for i := 0; i < len(arr); i++ {
  2. fmt.Println(arr[i])
  3. }

不过大部分时候,我们都是使用for rang循环:

  1. for i, v := range arr {
  2. fmt.Println("索引是:", i, "值是:", v)
  3. }

同样类型的数组是可以相互赋值的,不同类型的不行,会编译错误。那么什么是同样类型的数组呢?Go语言规定,必须是长度一样,并且每个元素的类型也一样的数组,才是同样类型的数组。

  1. arr := [5]int{1, 2, 3, 4, 5}
  2. var arr2 [5]int = arr //可以
  3. var arr3 [3]int = arr //不可以

指针数组和数组本身差不多,只不过元素类型是指针。

  1. arr := [5]*int{1: new(int), 3:new(int)}

这样就创建了一个指针数组,并且为索引1和3都创建了内存空间,其他索引是指针的零值nil,这时候我们要修改指针变量的值也很简单,如下即可:

  1. array := [5]*int{1: new(int), 3:new(int)}
  2. *array[1] = 1

以上需要注意的是,只可以给索引1和3赋值,因为只有它们分配了内存,才可以赋值,如果我们给索引0赋值,运行的时候,会提示无效内存或者是一个nil指针引用。

  1. panic: runtime error: invalid memory address or nil pointer dereference

要解决这个问题,我们要先给索引0分配内存,然后再进行赋值修改。

  1. arr := [5]*int{1: new(int), 3:new(int)}
  2. arr[0] =new(int)
  3. *arr[0] = 2
  4. fmt.Println(*arr[0])

函数间传递数组

在Go中,数组也是值类型,所以在函数间传递变量时,么就会整个复制,并传递给函数,如果数组非常大,比如长度100多万,那么这对内存是一个很大的开销。

  1. func main() {
  2. array := [5]int{1: 2, 3:4} //[0 2 0 4 0]
  3. modify(array)
  4. fmt.Println(array) //[0 2 0 4 0]
  5. }
  6. func modify(a [5]int){
  7. a[1] = 3
  8. }

通过上面的例子,可以看到,数组是复制的,原来的数组没有修改。我们这里是5个长度的数组还好,如果有几百万怎么办,有一种办法是传递数组的指针,这样,复制的大小只是一个数组类型的指针大小。

  1. func main() {
  2. array := [5]int{1: 2, 3:4} //[0 2 0 4 0]
  3. modify(&array)
  4. fmt.Println(array) //[0 333 0 4 0]
  5. }
  6. func modify(a *[5]int){
  7. a[1] = 333
  8. }

这里注意,数组的指针和指针数组是两个概念,数组的指针是*[5]int,指针数组是[5]*int,注意*的位置。

数组使用注意事项

  1. 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化。

  2. 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用。

  3. 数组创建后,如果没有赋值,有默认值

    数值类型数组:默认值为0

    字符串类型数组:默认值为""

    bool数组: 默认值为false

    指针数组: 默认值nil

  4. 使用数组的步骤:1.声明数组并开辟空间2.给数组各个元素赋值3.使用数组

  5. 数组的下标从0开始

  6. 数组下标必须在指定范围内使用,否则报panic:数组越界

  7. Go的数组属于值类型 ,在默认情况下是值传递,因此会进行值拷贝。数组间不会相互影响

  8. 如果想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式)

  9. 长度是数组类型的一部分,在传递函数参数时,需要考虑数组的长度

Go语言数组的更多相关文章

  1. GO语言数组和切片实例详解

    本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式: ...

  2. C语言 数组 列优先 实现

    C语言数组结构列优先顺序存储的实现 (GCC编译). 从行优先转换为列优先存储方式, 与行优先相比, 不同之处在于改变了数组维界基址的先后顺序, 从而改变了映像函数常量基址. /** * @brief ...

  3. C语言 数组 行优先 实现

    C语言数组结构行优先顺序存储的实现 (GCC编译). /** * @brief C语言 数组 行优先 实现 * @author wid * @date 2013-11-02 * * @note 若代码 ...

  4. 不可或缺 Windows Native (5) - C 语言: 数组

    [源码下载] 不可或缺 Windows Native (5) - C 语言: 数组 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 数组 示例cArray.h #ifn ...

  5. C语言数组

    在C语言中,对于三维或三维以上数组的使用并没有很好的支持,而且使用率也非常的低,后面会对三维数组做一些简单的分析,这篇文章主要以二维数组来探讨一些C语言中数组使用的相关概念和技巧. 1 一个var[i ...

  6. C语言数组:C语言数组定义、二维数组、动态数组、字符串数组

    1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...

  7. Go语言数组的使用

    Go 语言数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 相对于去声明number0 ...

  8. Go 语言数组

    Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 相对于去声明number0, number ...

  9. C语言 > 数组和指针

    C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...

  10. Go语言数组和切片的原理

    目录 数组 创建 访问和赋值 切片 结构 初始化 访问 追加 拷贝 总结 数组和切片是 Go 语言中常见的数据结构,很多刚刚使用 Go 的开发者往往会混淆这两个概念,数组作为最常见的集合在编程语言中是 ...

随机推荐

  1. Python数据库连接池DBUtils

    Python数据库连接池DBUtils   DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不 ...

  2. MySQL函数转储存(当前月数据同步)

    BEGIN declare a1 int default 0;#第一次循环的循环变量 declare a2 int default 0; declare b1 int default 0; decla ...

  3. 一张图说明TCP和UCP协议

    图片来自网络. 本来不想打字了,但是博客园有字数限制... 第一次 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认:SYN:同步序列编号( ...

  4. python 13 常用模块 一

    一.time模块 1.time.time()获取当前时间戳,返回长整型 2.time.localtime() 获取当地结构化时间,time.gmtime()获取格林尼治时间   一图需要传入匹配格式, ...

  5. 调用Excel宏批量处理文件

    '1.用户可以任意选择文件夹进行遍历 '2.限定遍历时仅搜索EXCEL文件(你可以改变文件类型) '这个程序要先在“引用”下选择"microsoft scripting runtime&qu ...

  6. RF自动化测试

    1.自动化分层:UI层实现界面自动化,Service层实现接口自动化,Unit层实现单元测试. 2.UI自动化测试常见的工具有:QTP,AutoIt,Selenium.Selenium是做Web测试最 ...

  7. WCF系列_WCF如何选择不同的绑定

    内容转载自<WCF核心技术> 开发者不用直接操作信道范型,而是由WCF根据服务OperationContract来选择合适的信道范型.大多数信道范型都有无会话两种变体.有会话信道会在客户端 ...

  8. godoc

    Godoc-一个Go代码文档化工具 Python - Docstring Java - javadoc

  9. sql中varchar(n),nvarchar(n) 长度性能及所占空间分析

    sql中varchar(n),nvarchar(n) 长度性能及所占空间分析 1.varchar(n),nvarchar(n) 中的n怎么解释: nvarchar(n)最多能存n个字符,不区分中英文. ...

  10. 团队-爬虫豆瓣top250项目-模块测试过程

    模块测试: 项目托管平台地址:https://github.com/gengwenhao/GetTop250.git 模块测试:"获取250排名的全部电影信息"功能,测试方法:手动 ...