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
相关推荐
千寻girling3 小时前
Koa.js 教程 | 一份不可多得的 Node.js 的 Web 框架 Koa.js 教程
前端·后端·面试
程序员清风3 小时前
北京回长沙了,简单谈谈感受!
java·后端·面试
何中应3 小时前
请求头设置没有生效
java·后端
NPE~3 小时前
自动化工具Drissonpage 保姆级教程(含xpath语法)
运维·后端·爬虫·自动化·网络爬虫·xpath·浏览器自动化
凡人叶枫3 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
春日见4 小时前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
锐意无限4 小时前
Swift 扩展归纳--- UIView
开发语言·ios·swift
低代码布道师4 小时前
Next.js 16 全栈实战(一):从零打造“教培管家”系统——环境与脚手架搭建
开发语言·javascript·ecmascript
宋小黑4 小时前
JDK 6到25 全版本网盘合集 (Windows + Mac + Linux)
java·后端
念何架构之路4 小时前
Go进阶之panic
开发语言·后端·golang