在 Go 语言中,有两个比较雷同的内置函数,分别是 new
和 make
方法,其主要用途都是用于分配相应类型的内存空间。
在 Go 语言中,new
和 make
都是用于内存分配的关键字,但它们的用途和行为有所不同。理解这两者的差异,对于编写高效且可维护的 Go 代码至关重要。本文将详细解释这两者的含义、用法以及它们之间的区别。

一、new
关键字
new
关键字用于为某个类型分配内存并返回该类型的指针。
看上去 new
和 make
都是分配内存的,那他们有什么区别呢?这个细节点也成为了不少 Go 语言工程师的面试题之一,值得大家一看。
在这篇文章中我们将来解答这个问题。

基本特性
make
在 Go 语言中,内置函数 make
仅支持 slice
、map
、channel
三种数据类型的内存创建,其返回值是所创建类型的本身,而不是新的指针引用。
函数签名如下:
go
func make(t Type, size ...IntegerType) Type
具体使用示例:
go
func main() {
v1 := make([]int, 1, 5)
v2 := make(map[int]bool, 5)
v3 := make(chan int, 1)
fmt.Println(v1, v2, v3)
}
在代码中,我们分别对三种类型调用了 make
函数进行了初始化。你会发现有的入参是有多个长度指定,有的没有。
这块的区别主要是长度(len)和容量(cap)的指定,有的类型是没有容量这一说法,因此自然也就无法指定。
输出结果:
css
[0] map[] 0xc000044070
有一个细节点要注意,调用 make
函数去初始化切片(slice)的类型时,会带有零值,需要明确是否需要。
见过不少的小伙伴在这上面踩坑。
new
在 Go 语言中,内置函数 new
可以对类型进行内存创建和初始化。其返回值是所创建类型的指针引用 ,与 make
函数在实质细节上存在区别。
函数签名如下:
dart
func new(Type) *Type
具体使用示例:
go
type T struct {
Name string
}
func main() {
v := new(T)
v.Name = "煎鱼"
}
从上面的例子的效果来看,是不是似曾相似?其实与下面这种方式的一样的:
go
func main() {
v := T{}
v.Name = "煎鱼"
}
输出结果均是:
css
&{Name:煎鱼}
其实 new
函数在日常工程代码中是比较少见的,因为他可被替代。
一般会直接用快捷的 T{}
来进行初始化,因为常规的结构体都会带有结构体的字面属性:
csharp
func NewT() *T {
return &T{Name: "煎鱼"}
}
这种初始化方式更方便。
区别在哪里
可能会有的小伙伴会疑惑一点,就是 new
函数也能初始化 make
的三种类型:
go
v1 := new(chan bool)
v2 := new(map[string]struct{})
那 make
函数的区别,优势是什么呢?
本质上在于 make
函数在初始化时,会初始化 slice
、chan
、map
类型的内部数据结构,new
函数并不会。
例如:在 map
类型中,合理的长度(len)和容量(cap)可以提高效率和减少开销。
更进一步的区别:
make
函数:
-
- 能够分配并初始化类型所需的内存空间和结构,返回引用类型的本身。
- 具有使用范围的局限性,仅支持
channel
、map
、slice
三种类型。 - 具有独特的优势,
make
函数会对三种类型的内部数据结构(长度、容量等)赋值。
new
函数:
-
- 能够分配类型所需的内存空间,返回指针引用(指向内存的指针)。
- 可被替代,能够通过字面值快速初始化。
三、new
和 make
的差异
-
用途不同:
new
用于为某个类型分配内存并返回该类型的指针。适用于结构体、数组、切片、映射等类型的内存分配,但不负责初始化数据。make
专门用于初始化切片、映射和通道。它会分配内存并且初始化这些数据结构。
-
返回值类型不同:
new
返回的是类型的指针(*T
),而make
返回的是具体类型本身(例如,map
、chan
或[]T
)。
-
适用场景不同:
new
适用于任何类型的内存分配,但不会初始化数据。它适用于需要指针的类型。make
只适用于切片、映射和通道,它会初始化底层的数据结构。
-
初始化行为:
new
分配的内存会被初始化为零值。例如,对于整数类型,new(int)
会分配一个值为0
的内存。make
会为切片、映射和通道分配内存并进行初始化。比如,对于make([]int, 5)
,它不仅会分配一个长度为 5 的切片,还会初始化切片的元素。
四、总结
new
:用于为任意类型分配内存,并返回指向该类型的指针。适用于结构体、数组等类型。返回值是指针,内存初始化为零值。make
:专门用于初始化切片、映射和通道,并返回相应的对象。适用于切片、映射、通道。返回值是对象本身,且已被初始化。
理解这两个关键字的差异,有助于我们更好地掌握 Go 语言的内存管理和数据结构初始化,从而编写更加高效和健壮的程序。