make([]*T, n) 创建的是长度为 n 的 nil 指针切片,因 Go 仅分配底层数组空间而不初始化元素,所有指针默认为 nil,需显式循环赋值 &T{} 才可安全解引用。
为什么
创建的是 nil 指针切片,而不是已初始化的结构体指针
因为
只分配切片底层数组空间,每个元素默认是
——Go 不会自动调用
初始化每个位置。你拿到的是长度为
的
,但所有指针都为
,直接解引用会 panic。
常见错误现象:
典型使用场景:需要预分配固定大小的结构体指针容器,比如缓存池、批量请求参数、图节点邻接表
必须显式循环赋值:
,或用
动态构造
性能影响:一次性
再循环赋值,比反复
更快(避免多次扩容);但若后续大部分位置实际不使用,浪费内存
用
预分配 + 循环初始化的正确写法
这是最可控、最常用于已知容量且需全量初始化的场景。关键点在于别漏掉循环赋值,也别误写成
(那是值类型,不是指针)。
正确示例:
错误写法:
→ 类型不匹配;
→ 容量够但长度为 0,
不进循环
如果结构体字段多或含非零初始值,建议封装为工厂函数:
用
动态构造指针切片的适用边界
适合容量不确定、按需添加、或初始化逻辑较重(比如要查数据库、读文件)的场景。它更灵活,但要注意底层数组可能多次复制。
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
常见错误:直接
却忘了变量声明时没初始化,其实没问题——
切片可直接
性能提示:如果预估最终长度,用
再
,能避免中间扩容
注意别在循环里重复取地址同一变量:
正确做法是在循环内声明新变量或用
嵌套结构体指针切片(如
)初始化容易忽略的二级分配
二维指针切片不是自动“递归初始化”的。第一层
后,每个
元素仍是
,必须单独初始化。
立即学习
“
go语言免费学习笔记(深入)
”;
典型坑:
→ panic:index out of range,因为
是
正确步骤:先初始化外层,再对每个外层元素
简短示例:
兼容性提醒:这种嵌套在 GC 压力和内存局部性上不如扁平化结构(如单个
加索引计算),高并发或大数据量时值得权衡
事情说清了就结束。最常被跳过的其实是第二层初始化,尤其是嵌套两层以上时,panic 报错位置离实际出错点很远。
make([]*T, n)make([]*T, n)nil&T{}n[]*Tnilpanic: runtime error: invalid memory address or nil pointer dereferencefor i := range s { s[i] = &T{} }appendmakeappendmakes[i] = T{}type User struct { Name string }
users := make([]*User, 3)
for i := range users {
users[i] = &User{Name: fmt.Sprintf("user-%d", i)}
}users[i] = User{"xxx"}users = make([]*User, 0, 3)rangefunc newUser(name string) *User { return &User{Name: name, CreatedAt: time.Now()} }appendvar s []*User; s = append(s, &User{})nilappendmake([]*User, 0, estimatedSize)appendvar u User
for _, name := range names {
u.Name = name
s = append(s, &u) // ❌ 全部指向同一个 u 地址
}u := User{Name: name}[][]*Tmake([][]*T, n)[][T]nilgrid := make([][]*User, 3); grid[0][0] = &User{}grid[0]nilmake([]*User, cols)grid := make([][]*User, rows)
for i := range grid {
grid[i] = make([]*User, cols)
for j := range grid[i] {
grid[i][j] = &User{}
}
}[]*User