Go 的数组是 固定长度、同一类型 的一组数据,定义后长度不可改变,是一种值类型。
数组的声明方式
(1)声明时指定长度
Go
var a [3]int
长度为 3,默认值全是 0。
(2)声明并初始化
Go
b := [3]int{1, 2, 3}
(3)自动推断长度
使用 ...:
Go
c := [...]int{1, 2, 3, 4}
Go 编译器会自动计算长度为 4。
(4)指定索引初始化
Go
d := [...]int{0: 100, 3: 300}
索引 0 的值为 100,索引 3 的值为 300,其他为 0。
数组的长度是类型的一部分
Go
var a [3]int
var b [4]int
a 和 b 是不同的类型,不能互相赋值。
数组是值类型(重点)
Go 的数组 赋值、传参都会 复制整个数组,而不是引用。
Go
func modify(x [3]int) {
x[0] = 100
}
func main() {
a := [3]int{1,2,3}
modify(a)
fmt.Println(a) // => [1 2 3]
}
原数组不会被修改。
如果想改变原数组,必须使用指针:
Go
func modify(x *[3]int) {
x[0] = 100
}
获取数组长度
Go
len(a)
数组的遍历
Go
for i, v := range a {
fmt.Println(i, v)
}
或传统方式:
Go
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
多维数组
Go 支持多维数组:
Go
var m [2][3]int
初始化:
Go
matrix := [2][3]int{
{1, 2, 3},
{4, 5, 6},
}
数组 vs 切片(slice)区别
这是实际开发最重要的部分:
数组(array)
-
长度固定
-
值类型
-
很少直接使用
切片(slice)
-
底层基于数组
-
长度可变
-
引用类型(类似动态数组)
-
Go 日常开发使用频率远高于数组
简单理解:
数组更像底层结构,切片才是 Go 主力容器。
示例:切片是引用类型,修改会影响原数据:
Go
s := []int{1,2,3}
s[0] = 100
数组的典型使用场景
虽然数组不常单独使用,但以下情况很常见:
用在固定长度的数据结构
例如:
-
IPv4 地址
[4]byte -
MD5 哈希
[16]byte -
SHA256 哈希
[32]byte
做底层性能优化(少变更、固定大小)
总结表
| 项目 | 数组 Array | 切片 Slice |
|---|---|---|
| 长度 | 固定 | 可变 |
| 类型 | 值类型 | 引用类型 |
| 内存分配 | 整块分配 | 指向底层数组 |
| 赋值/传参 | 拷贝整个数据 | 拷贝指针,指向同一底层数据 |
| 使用频率 | 较低 | 极高 |