1. 程式人生 > >golang 內建函式new()和make()的區別

golang 內建函式new()和make()的區別

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資料結構

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 用於可以初始化其內部的資料結構並準備好將要使用的值。