Go 数组和切片

本文将介绍 Go 中数组和切片这两个用于存储序列数据的容器。

一、数组

1. 什么是数组?

在 Go 中,数组是一个固定长度、固定元素类型的序列。

2. 数组创建

1
2
3
4
5
6
7
8
9
10
11
// 声明长度,声明元素类型,不赋值
var 数组名 [元素数量]元素类型

// 声明长度,声明元素类型,赋值
var 数组名 = [元素数量]元素类型{元素1, 元素2}

// 声明长度,声明元素类型,根据索引赋值
var 数组名 = [元素数量]元素类型{1: 元素1, 4: 元素2}

// 省略长度,声明元素类型,赋值
var 数组名 = [...]元素类型{元素1, 元素2}

3. 数组比较

当两个数组的长度相同、元素类型相同时,可以直接通过 ==!= 对两个数组的相等与否做判断。

二、切片

1. 什么是切片?

数组长度固定,在许多场景下不够灵活。

为此,Go 设计了切片,它是对数组的包装,可以看作是动态数组。

2. 切片创建

1
2
3
4
5
6
7
8
9
10
11
// 声明元素类型,不赋值
var slice []元素类型

// 声明元素类型,赋值
var slice = []元素类型{元素1, 元素2}

// 基于数组/切片
var slice = 数组/切片[[左边界]:[右外边界]]

// 通过 make 函数
var slice = make([]元素类型, 长度[, 容量])

需要注意的是:

  • 基于数组:

    • 左边界:
      • 可以忽略,忽略时值为 0
      • 数组[左边界] 将包含在切片内作为切片开头
    • 右外边界:
      • 可以忽略,忽略时值为 “数组/底层数组的长度”,即 cap
      • 数组[右外边界 - 1] 将包含在切片内作为切片末尾
  • 通过 make 函数:

    • 容量可以省略

      其作用具体见下文

3. 切片的底层结构

1
2
3
4
5
type slice struct {
array unsafe.Pointer
len int
cap int
}

其中,

  • array 为指针,指向底层数组
  • len 表示长度
  • cap 表示容量,即底层数组可以提供的容量

4. 自动扩容机制

当底层数组可以提供的容量不够时,Go 语言将会开辟一个新的更大的空间,拷贝内容,将切片指针指向新空间,从而实现自动的、用户无感的扩容。

原 cap <= 256 时,新 cap = 2 * 原 cap

否则,新 cap = [1.25 ~ 2] * 原 cap

5. 常用方法

(1) len()

1
len := len(slice)

用于计算长度。

(2) cap()

1
cap := cap(slice)

用于计算容量。

(3) append()

1
slice2 := append(slice1, 元素1, 元素2)

用于向切片中添加元素。

(4) copy()

1
copy(slice, sourceSlice)

用于拷贝元素。

参考