Go语言中new与make的区别详解

Mia
Mia
发布时间:2026-10-15 | 5人浏览过
原创

在Go语言开发中,new和make是两个常用的内置函数,但它们的用途和返回值截然不同。new负责分配内存并初始化为零值,返回类型指针;而make专门用于初始化slice、map和chan等引用类型,直接返回该类型实例。理解两者的差异对于编写健壮的Go代码至关重要。

深入理解 new 函数

new是Go的内置函数,主要用于为给定类型分配内存。其核心特征是只分配、不初始化具体业务数据,而是将内存空间填充为该类型的零值(Zero Value)。

第1步:了解 new 的行为特征

根据Go语言规范,func new(Type) *Type:

  • 输入:一个类型(Type),而非具体值。
  • 输出:指向新分配内存的地址指针(*Type)。
  • 内存状态:分配的内存会被清零。例如,整型零值为0,字符串零值为空串"",指针零值为nil。

由于Go不支持函数重载,new无法接受额外的初始化参数。这意味着使用new创建的对象必须在使用前手动赋值字段,否则都是零值。

第2步:观察 new 的使用示例

以下代码展示了使用new为基本类型和指针类型分配内存的情况:

a := new(int)
fmt.Printf("类型为:%T, 值为:%v\n", a, a)
fmt.Printf("类型为:%T, 值为:%v\n", *a, *a)

b := new(string)
fmt.Printf("类型为:%T, 值为:%v\n", b, b)
fmt.Printf("类型为:%T, 值为:%v\n", *b, *b)

运行结果可见,a是指向int的指针,解引用后值为0;b是指向string的指针,解引用后为空字符串。若对指针类型使用new,如c := new(*int),其内部指针将为nil。

第3步:new 与 &struct{} 的对比

虽然new(struct{})和&struct{}都能获取结构体指针,但后者允许在声明时进行字段初始化,而前者仅能获取零值结构体指针。因此,在实际工程中,初始化结构体更推荐直接使用字面量或&操作符。

深入理解 make 函数

make是另一个内置函数,但它有严格的适用范围:仅用于 slice(切片)、map(映射)和 chan(通道)这三种引用类型。

第1步:认识 make 的核心作用

函数签名:func make(t Type, size ...IntegerType) Type。

  • 输入:类型及可选的长度/容量参数。
  • 输出:返回该类型的实例本身(非指针),因为这三种类型本身就是引用类型,包含内部指针指向底层数据结构。
  • 初始化:除了分配内存,make还会对底层数据结构进行必要的初始化。例如,map会建立哈希表,slice会分配数组头部,chan会分配缓冲区队列。

如果试图对指针、数组或未初始化的slice使用make,编译器会报错。

在编译阶段,Go编译器会将make关键字根据参数类型转换为不同的操作节点(如OMAKESLICE、OMAKEMAP、OMAKECHAN),最终调用不同的运行时函数完成复杂的结构初始化。这正是make与new最根本的区别之一。

第2步:实际应用场景分析

Slice(切片):

未初始化的slice长度为0,直接访问会引发panic。

var s []int
// fmt.Println(s[0]) // Panic: index out of range

使用make指定长度可安全访问:

s := make([]int, 5)
fmt.Println(s[0]) // 输出 0,已自动初始化为零值

注意:slice的容量(cap)可以大于长度(len),超出长度的部分仍可追加元素。

Map(映射):

Map在未初始化前为nil,不能直接写入,否则会panic。make会创建空的哈希桶,支持立即写入:

m := make(map[string]int)
m["key"] = 10 // 成功

Chan(通道):

通道初始化时指定的是缓冲区的长度。无缓冲通道会导致发送方阻塞直到接收方就绪。

new 与 make 的核心差异总结

为了清晰区分,以下是两者的关键对比:

  • 适用类型:new适用于所有类型(包括基本类型、结构体、指针);make仅适用于 slice、map、chan。
  • 返回值:new返回类型指针(*Type);make返回类型本身(Type),即引用类型实例。
  • 内存处理:new仅分配内存并清零(Zero Value),不进行复杂初始化;make分配内存并进行结构化初始化(如建立hash表、分配底层数组)。
  • 堆栈分配:两者都可能根据逃逸分析分配到栈或堆。通常小对象或局部变量使用new可能在栈上分配以优化性能;而make创建的slice/map底层数据往往较大,容易逃逸到堆内存,由垃圾回收器管理。

简而言之,如果你需要创建一个基础数据类型的指针,使用new;如果你需要创建一个可用的切片、映射或通道,必须使用make。

以上就是Go语言中new与make的区别详细内容,更多关于Go语言内存管理与初始化的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表