Go语言中new()与make()的核心区别及适用场景
Go语言的new()和make()常被初学者混用,但二者在设计初衷与适用范围上截然不同。new()是通用内存分配器,返回指向零值的指针;而make()专用于内置引用类型(切片、映射、通道),负责完成底层结构的初始化。理解其差异是编写健壮Go代码的基础。
核心结论速览
在使用Go时,区分这两个函数的最简方式如下:
new(Type):通用内存分配。返回*Type指针。内存已分配但内容为零值(Zero Value),未进行对象特有的初始化逻辑。make(Type, ...):仅限slice、map、chan。返回Type引用(非指针)。不仅分配内存,还完成了特定类型的内部结构初始化(如Map的哈希桶、Slice的底层数组头)。
new(): 通用的零值分配
new 是Go的内建函数之一,其签名简单明了:
func new(Type) *Type
工作原理与示例
new 的主要任务是分配内存并将该内存清零。它并不执行该类型的构造函数或初始化逻辑(Go中自定义类型无传统意义上的构造函数,而是靠工厂函数或字面量语法)。它返回一个指向新分配的、类型为 Type 的变量的指针。
我们可以用标准库逻辑模拟 new 的行为:
// 模拟 new(int)
func newInt() *int {
var i int // 默认零值 0
return &i
}
ptr := newInt()
// 等同于 ptr := new(int)
在这个例子中,someInt 是一个指向整数的指针。虽然内存空间已经准备好,但如果 Type 是一个复杂的结构体,new 只会将每个字段重置为其默认零值,而不会自动建立依赖关系(例如指针字段会变为 nil)。
make(): 专用的引用类型构建器
make 也是内建函数,但它的行为比 new 复杂得多。官方文档明确规定:make 只能用于 slice、map 和 chan 这三种内置引用类型。它返回的是这些类型本身(引用/句柄),而不是它们的指针。
1. Slice (切片)
切片的底层包含三个部分:指向数组的指针、长度(len)、容量(cap)。make 会分配底层数组并设置这两项参数。
s := make([]int, 0, 10)
- 第二个参数(size):指定切片的初始长度。
- 第三个参数(capacity)(可选):指定切片的容量。如果省略,容量等于长度。
注意:如果省略第三个参数且只传了长度,则 cap 与 len 相等。
2. Map (映射)
Map 是基于哈希表实现的。使用 make 可以预先分配一定数量的哈希桶以减少扩容开销。
m := make(map[string]int, 100)
这里的 100 提示分配器预留容纳约100个键值对的空间。若不提供此参数,Map 仍可正常使用,但在插入大量数据时会频繁触发重新哈希(rehash),影响性能。
3. Chan (通道)
通道用于goroutine间的通信。make 在此处用于创建带缓冲或无缓冲的通道。
c1 := make(chan int) // 无缓冲
c2 := make(chan int, 100) // 缓冲容量为100
如果传入的缓冲区容量为 0 或被忽略,则该通道是无缓冲的(发送操作将阻塞直到接收者就绪);否则为有缓冲通道。
对比总结
| 特性 | new(Type) |
make(Type, ...) |
|---|---|---|
| 返回值类型 | *Type (指针) |
Type (引用类型本身) |
| 适用类型 | 任何类型 | 仅 slice, map, chan |
| 是否初始化 | 仅内存清零 | 分配内存 + 内部结构初始化 |
一句话总结:new 用来“申请空白”,make 用来“组装工具”。
以上就是Go语言中new()和make()的核心区别详解,更多关于Go基础知识的学习资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









