Skip to content
目录

数组与切片 (Arrays and Slices)

在 Go 语言中,数组和切片是两个紧密相关但用途迥异的数据结构。新手常因为混淆它们而踩坑。

1. 数组 (Array)

数组是固定长度的、同一类型的数据集合。

1.1 定义与初始化

数组的长度是类型的一部分,[3]int[4]int 是完全不同的两种类型。

go
var a1 [3]int                  // 默认初始化为 [0 0 0]
var a2 = [3]int{1, 2, 3}       // 指定初始值
a3 := [...]int{1, 2, 3, 4, 5}  // 自动推断长度为 5

1.2 值类型特性

Go 语言中的数组是值类型。这意味着将一个数组赋值给另一个数组,或者作为函数参数传递时,会发生完全拷贝(Copy)。

go
a := [3]int{1, 2, 3}
b := a        // b 是 a 的完整副本
b[0] = 100
fmt.Println(a) // [1 2 3] (a 不受影响)
fmt.Println(b) // [100 2 3]

2. 切片 (Slice)

切片是对数组一个连续片段的引用。它更加灵活,长度可变,是 Go 开发中最常用的数据结构。

2.1 内部结构

切片本质上是一个结构体,包含三个字段:

  1. Pointer: 指向底层数组中切片开始位置的指针。
  2. Len: 切片当前的长度(元素个数)。
  3. Cap: 切片的容量(从切片开始位置到底层数组末尾的长度)。

2.2 创建切片

方式一:从数组切取

go
arr := [...]int{1, 2, 3, 4, 5}
s1 := arr[1:3] // 包含 arr[1], arr[2],即 [2 3]

方式二:直接声明

go
var s []int // nil 切片,len=0, cap=0

方式三:使用 make (推荐)

go
// make([]Type, len, cap)
s2 := make([]int, 5, 10) // 长度为5,容量为10

2.3 切片的追加 (append)

使用 append 向切片追加元素。如果切片容量不够,Go 会自动扩容(分配一个新的更大的底层数组,并将旧数据拷贝过去)。

go
var s []int
s = append(s, 1)       // [1]
s = append(s, 2, 3, 4) // [1 2 3 4]
s = append(s, s...)    // 追加另一个切片 [1 2 3 4 1 2 3 4]

扩容策略

当容量小于 256 时,每次扩容通常是翻倍;当容量较大时,扩容系数会逐渐降低(约 1.25 倍),以节省内存。

2.4 切片的拷贝 (copy)

由于切片是引用类型,简单的赋值 s2 := s1 只是拷贝了指针(浅拷贝)。如果需要独立的副本,必须使用 copy

go
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src) // 将 src 内容拷贝到 dst
dst[0] = 100
fmt.Println(src) // [1 2 3] (不受影响)

3. 性能优化建议

3.1 预分配容量

如果你知道大概需要存储多少元素,建议在 make 时指定 cap,避免频繁的内存分配和扩容。

go
// ❌ 差:多次扩容
s := make([]int, 0)
for i := 0; i < 1000; i++ {
    s = append(s, i)
}

// ✅ 优:一次分配
s := make([]int, 0, 1000)
for i := 0; i < 1000; i++ {
    s = append(s, i)
}

3.2 避免内存泄漏

如果你有一个很大的数组,但只切片引用了其中一小部分,整个大数组都无法被垃圾回收(GC)。

go
func getSmallSlice() []int {
    bigArr := [1000000]int{...}
    // ❌ 导致 bigArr 无法释放
    return bigArr[:10] 
}

func getSmallSliceFixed() []int {
    bigArr := [1000000]int{...}
    small := make([]int, 10)
    // ✅ 拷贝数据,bigArr 可以被回收
    copy(small, bigArr[:10]) 
    return small
}

扫描下方二维码,私信【训练营】可进行咨询和报名。 微信公众号二维码

最后一次更新于:

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情