Go语言中的内建函数new和make是两个用于内存分配的原语(allocation primitives),其功能相似,却有本质区别。
new和make的区别
new
官方文档
// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type
即内建函数 new 用来分配内存,它的第一个参数是一个类型,不是一个值,它的返回值是一个指向新分配类型零值的指针
make
//The make built-in function allocates and initializes an object
//of type slice, map, or chan (only). Like new, the first argument is
// a type, not a value. Unlike new, make's return type is the same as
// the type of its argument, not a pointer to it.
func make(t Type, size ...IntegerType) Type
即内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),跟 new 类似,第一个参数也是一个类型而不是一个值,跟 new 不同的是,make 返回类型的引用而不是指针,而返回值也依赖于具体传入的类型,
new和其他语言中的同名函数一样:
new(t)分配了零值填充的T类型的内存空间,并且返回其地址
,即一个*t类型的值。
它并不初始化内存,只是将其置零。*t指向的内容的值为零(zero value)。注意并不是指针为零。
make(t, args)与new(t)的功能区别是,make只能创建slice、map和channel,,并且返回一个初始化的(而不是置零),类型为t的值(而不是*t)。
为什么slice、map和channel要由make创建呢?
先来看一下以上三个数据结构的源码
slice
type slice struct {
array unsafe.Pointer
len int
cap int
}
slice的结构体由3部分构成,Pointer 是指向一个数组的指针,len 代表当前切片的长度,cap 是当前切片的容量。
map
// A header for a Go map.
type hmap struct {
count int
flags uint8
B uint8
noverflow uint16
hash0 uint32
buckets unsafe.Pointer
oldbuckets unsafe.Pointer
nevacuate uintptr
extra *mapextra
}
channel
type hchan struct {
qcount uint
dataqsiz uint
buf unsafe.Pointer
elemsize uint16
closed uint32
elemtype *_type
sendx uint
recvx uint
recvq waitq
sendq waitq
lock mutex
}
可以看出三个类型的背后都引用了使用前必须初始化
的数据结构
而只有make 用于可以初始化
其内部的数据结构并准备好将要使用的值。