返回

深挖golang中的数组和切片:概念、使用和差异

后端

golang之数组切片傻傻分不清楚

对于 Go 开发人员来说,Slice 是日常工作中使用频率较高的数据结构。在深入探究 Slice 之前,我们先来了解一下数组。数组是大家都很熟悉的,它的数据结构比较简单,在内存中是连续的。举个例子,一个存储了 10 个数字的数组在内存中可以表示为:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

每个元素都占据一个固定大小的内存空间,并且在内存中是连续存放的。数组的优点是访问元素的速度很快,因为我们可以直接通过索引来访问。

然而,数组也有一些缺点。首先,它的长度是固定的,一旦创建就无法改变。如果我们需要动态地调整数组的大小,就需要创建一个新数组并复制元素,这是一个比较耗时的操作。其次,数组是值类型,这意味着当我们把一个数组赋值给另一个变量时,实际上是创建了一个新的数组副本。如果数组很大,这可能会导致性能问题。

Slice 是 Go 中引入的一种比数组更灵活的数据结构。它本质上是数组的一个引用 ,可以动态地改变其长度。与数组类似,Slice 也在内存中连续存储元素,但它不存储元素的实际值,而是存储了一个指向底层数组的指针和一个表示 Slice 长度和容量的结构。

+-------+-------------------+
| Slice |  length | capacity |
+-------+-------------------+
|       |    5    |    10    |
+-------+-------------------+
|       |    [指向底层数组的指针]    |
+-------+-------------------+

Slice 的优点有很多。首先,它可以动态地改变长度,而不需要创建新数组。当我们向 Slice 中添加或删除元素时,只需要更新 Slice 的长度即可。其次,Slice 是引用类型,这意味着当我们把一个 Slice 赋值给另一个变量时,实际上是把对底层数组的引用传递给了另一个变量。这可以显著提高性能,尤其是在 Slice 很大的情况下。

在使用 Slice 时,需要注意以下几点:

  • Slice 的长度不能超过底层数组的容量。
  • 当 Slice 的长度改变时,底层数组的容量不会改变。
  • 我们可以使用 make() 函数来创建新的 Slice,也可以通过对数组进行切片操作来创建 Slice。

切片操作是一种创建 Slice 的语法糖,它使用以下格式:

[]T[low:high]

其中,T 是元素类型,lowhigh 是可选的索引。low 指定切片的起始索引,high 指定切片的结束索引。如果省略 low,则表示从头开始;如果省略 high,则表示一直到尾。

例如,以下代码创建了一个从数组 arr 中的第 2 个元素开始,到第 5 个元素结束的 Slice:

slice := arr[1:5]

Slice 在 Go 中是一个非常有用的数据结构,它结合了数组和指针的优点,既可以动态地改变长度,又可以高效地访问元素。在实际开发中,Slice 是比数组更常用的数据结构。