Go基础篇-数组
1 序
在Go语言中,数组是数据管理中至关重要的组件。它们作为核心数据结构,为开发者提供了灵活性、性能和便利性,本文将带您了解Go语言复合数据类型的数组。并深入探讨它的特性、用法和常见操作。
在使用数组的时候,我们会使用一些函数来实现,这里我们将介绍Go语言中的内置函数。
2 内置函数
Go语言提供了一些内置函数(Built-in Functions),这些函数是在编译器中实现的,并且可以直接使用,无需导入任何包。以下是一些常用的Go内置函数:
1 | 1. len(): 返回字符串、数组、切片、字典或通道的长度。 |
除了以上列出的内置函数,Go语言还提供了其他很多有用的内置函数,涵盖了各种操作和功能,例如类型转换、数学计算、字符串处理等。你可以通过查看官方文档来获取完整的内置函数列表和详细的使用说明。
需要注意的是,虽然这些函数是内置的,但它们也可以被重新定义为普通的标识符。所以,如果你在自己的代码中使用了跟内置函数同名的标识符,那么内置函数将会被覆盖。
3 数组底层原理
在Go语言中,数组是一种值类型。当你创建一个数组时,Go会在内存中为该数组分配一个连续的内存块,每个元素都占据该内存块中的一部分。数组中的每个元素都可以通过其索引直接访问。因为这种内存布局,数组的访问速度非常快。
下面是一个简单的图解,展示了一个长度为3,元素类型为int的数组在内存中的布局。
内存地址 | 0x00 | 0x04 | 0x08 |
---|---|---|---|
索引 | 0 | 1 | 2 |
值 | arr[0] | arr[1] | arr[2] |
当你将一个数组赋值给另一个数组时,Go会创建一个新的内存块,并将原数组的所有元素值复制到新的内存块。这就是为什么说Go中的数组是值类型,而不是引用类型。这也意味着如果你在函数中修改了一个数组,原数组不会被修改,除非你使用指针或者切片。
4 数组特点
数组是一种固定长度的数据结构,用于存储相同类型的元素序列。声明数组时,需要指定其长度,这意味着数组的大小在创建后不可更改。数组的索引从0开始,提供了快速访问元素的方式。然而,由于其固定长度的特性,数组在某些场景下的灵活性受到限制。
数组具有以下特点:
- 数组长度不可变,且它不是引用类型。
- 数组里数据是相同类型数据。
- 数组中元素可以是任意的原始类型,比如int、string等。
- 一个数组中元素的个数被称为数组长度。
- 数组的长度属于类型一部分,也就是[5]int和[10]int属于不同类型。
- 数组占用内存连续性,也就是数组中的元素被分配到连续内存地址中,因而索引数组元素速度非常快。
5 定义数组
Go语言中,数组的声明和实现可以通过以下方式进行:
5.1 var关键字声明
在Go语言中,可以使用var关键字来声明一个数组。数组的声明语法如下:
1 | var arrayName [size]dataType |
其中,arrayName是数组的名称,size是数组的大小, 而且size是必须要指定的,dataType是数组中元素的数据类型。
例如,声明一个包含5个整数的数组:
1 | var numbers [5]int |
在这个例子中,数组的名称是numbers,大小为5个整数元素,即[5]int。
声明完该数组,我们可以后面再针对该数组进行赋值。一般是直接用{}大括号赋值,或者通过索引设置数组元素。
1 | var numbers [5]int |
5.2 :=声明并初始化数组
在声明数组的同时,可以使用大括号{}来初始化数组的元素。例如:
1 | // 声明并初始化值 |
或者可以使用简化的声明和初始化方式:
1 | // 声明并初始化值 |
如果你不确定数组的长度,可以让Go编译器自动计算数组的长度,在初始化的时候,可以使用 …
1 | // 数组大小可以根据数组内容自动推断 |
这样,数组numbers就被声明并初始化为包含元素1到5的整数数组。
6 访问数组
可以通过索引来访问数组中的元素。索引从0开始,逐个递增。例如,要访问上面声明的数组numbers的第一个元素,可以使用numbers[0]
。例如:
1 | import "fmt" |
我们还可以通过len()
和cap()
函数计算数组的长度和容量
1 | import "fmt" |
7 遍历数组
有两种主要的方法可以遍历Go中的数组。你可以使用传统的for
循环,也可以使用range
关键字。
7.1 For关键字遍历
首先可以通过for关键字遍历,其中需要借助len()
函数计算数组长度。
1 | import "fmt" |
7.2 Range关键字遍历
也可以通过range关键字遍历数组,例如:
1 | import "fmt" |
如果不需要使用索引,可以通过下划线’_’代替:
1 | import "fmt" |
通常来说,我们使用for range
方式迭代可能会好一点,因为这种迭代可以保证不会出现数组越界的情况,每次迭代对数组的访问可以省略对下标越界判断,当然具体使用,因实际情况不同而不同。
8 修改数组元素
可以通过索引来修改数组中的元素。例如,要将上面声明的数组numbers的第一个元素修改为0,可以使用numbers[0] = 0
。
1 | import "fmt" |
当你把一个数组作为参数传给函数,然后在函数中修改数组的其中一个元素,这并不会改变原数组的值,因为参数值实际上是该数组的副本,例如:
1 | import "fmt" |
如果要想在函数中修改数组的值,可以通过指针实现。
1 | import "fmt" |
9 数组复制
在Go语言中,数组是值类型。当你将一个数组赋值给另一个变量时,会复制整个数组的内容,而不是复制对数组的引用。这意味着对一个数组的修改不会影响到另一个数组,例如
1 | import "fmt" |
这个例子中,虽然修改了arr1的第一个元素,但arr2并不受影响,因为在赋值时是将arr1的内容复制给了arr2,它们是完全独立的数组。
10 数组比较
在go语言中,可以使用比较运算符“==”或“!=”来进行数组比较,判断两个数组是否相等。
注意:只有当两个数组的所有元素都是相等的时候数组才是相等的,不能比较两个类型不同的数组,否则程序将无法完成编译。
1 | import "fmt" |
10.1 数组长度不同
根据数组特点我们知道,即便是元素类型相同,数组长度只要不同,编译器都认为这是两种不同的数据类型,所以数组无法通过==比较,编译器会直接报错。
1 | import "fmt" |
10.2 数组元素类型不同
如果数组的长度相同,数据类型不同,编译器同样认为这是两种不同的数据类型,所以数组也无法通过==比较,编译器会直接报错。
1 | import "fmt" |
11 总结
需要注意的是,在Go中数组的长度是固定的,因此无法直接删除或调整数组的大小。如果需要删除数组中的元素,可以使用切片来实现类似的效果,我们将在下一章节中介绍。
在Go语言中,数组类型是非常重要的类型,数组本身的赋值和函数传参都是通过复制的方式处理的,理解数组的底层原理有助于更好的使用数组,但是Go语言中很少直接使用数组,原因就是不同长度的数组因为类型不同无法直接赋值,我们下章节将介绍切片,看看切片的操作使用,欢迎阅读。