Go语言数组与切片的区别

数组与切片的区别

一句话结论:

数组是"值类型容器"
切片是"指向数组的引用视图"

再直白一点:

  • 数组:我自己就是数据

  • 切片:我只是看数据的一扇窗

  • 数组 = 盒子

  • 切片 = 指向盒子的标签

  • 复制盒子 → 内容独立

  • 复制标签 → 看同一个盒子

一、最本质的 4 个区别(核心)

|---------|---------------|---------------|
| 对比点 | 数组(array) | 切片(slice) |
| 类型 | 值类型 | 引用语义(结构体) |
| 长度 | 固定,类型的一部分 | 可变 |
| 内存 | 自己持有数据 | 指向底层数组 |
| 常用性 | 很少直接用 | Go 的主力 |

二、类型层面的区别(非常关键)

数组:长度是类型的一部分

复制代码
var a [3]int
var b [4]int

👉 a 和 b 是完全不同的类型

复制代码
a = b // ❌ 编译错误

切片:长度不是类型的一部分

复制代码
var s1 []int
var s2 []int

👉 无论多长,类型都一样

三、内存模型区别(理解一切 bug 的根源)

数组(独立内存)

复制代码
a := [3]int{1, 2, 3}
b := a
b[0] = 100

结果:

复制代码
a = [1 2 3]
b = [100 2 3]

👉 值拷贝

切片(共享底层数组)

复制代码
a := []int{1, 2, 3}
b := a
b[0] = 100

结果:

复制代码
a = [100 2 3]
b = [100 2 3]

👉 共享底层数组

四、作为函数参数的区别

数组传参:完整拷贝(非常重)

复制代码
func f(a [3]int) {
    a[0] = 100
}

func main() {
    x := [3]int{1, 2, 3}
    f(x)
    fmt.Println(x)
}

输出:

复制代码
[1 2 3]

切片传参:拷贝 slice 头(轻)

复制代码
func f(s []int) {
    s[0] = 100
}

func main() {
    x := []int{1, 2, 3}
    f(x)
    fmt.Println(x)
}

输出:

复制代码
[100 2 3]

五、长度与容量(数组没有 cap)

复制代码
a := [3]int{1, 2, 3}

len(a) // 3
cap(a) // ❌ 不存在

s := []int{1, 2, 3}

len(s) // 3
cap(s) // >= 3

👉 cap 是 slice 独有的概念

六、创建方式差异

数组(少见)

复制代码
a := [3]int{1, 2, 3}
a := [...]int{1, 2, 3} // 编译期推断

切片(主流)

复制代码
s := []int{1, 2, 3}
s := make([]int, 3)
s := make([]int, 0, 10)

七、为什么 Go 设计数组 + 切片两套?

一句话:

数组用于"确定大小的数据结构"
切片用于"动态、高效的数据处理"

数组适合:

  • 小型、固定大小
  • 值语义(拷贝安全)
  • 底层数据结构(如哈希桶)

切片适合:

  • 几乎所有业务代码
  • 传参
  • 集合、列表、缓冲区

八、工程级使用建议

✅ 99% 场景用切片

复制代码
func process(data []byte)

✅ 用数组的 3 种典型场景

1️⃣ 编译期固定大小

复制代码
var buf [32]byte // hash / uuid

2️⃣ 明确要值语义

复制代码
type Point struct {
    XY [2]int
}

3️⃣ 性能 / 底层库

复制代码
var table [256]byte
相关推荐
wuguan_1 小时前
C#:多态函数重载、态符号重载、抽象、虚方法
开发语言·c#
计算机学姐2 小时前
基于php的摄影网站系统
开发语言·vue.js·后端·mysql·php·phpstorm
Java水解2 小时前
【SpringBoot3】Spring Boot 3.0 集成 Mybatis Plus
spring boot·后端
whoops本尊2 小时前
Golang-Data race【AI总结版】
后端
全栈陈序员2 小时前
【Python】基础语法入门(二十)——项目实战:从零构建命令行 To-Do List 应用
开发语言·人工智能·python·学习
我不是程序猿儿2 小时前
【C#】ScottPlot的Refresh()
开发语言·c#
墨守城规2 小时前
线程池用法及原理
后端
Neolnfra2 小时前
渗透测试标准化流程
开发语言·安全·web安全·http·网络安全·https·系统安全
用户2190326527352 小时前
Spring Boot + Redis 注解极简教程:5分钟搞定CRUD操作
java·后端