Go语言中的内建函数new和make是两个用于内存分配的原语(allocation primitives)。对于初学者,这二者的区别也挺容易让人迷糊的。简单的说,new只分配内存,make用于slice,map,和channel的初始化。数组
这是一个用来分配内存的内建函数,可是与C++不同的是,它并不初始化内存,只是将其置零。也就是说,new(T)会为T类型的新项目,分配被置零的存储,而且返回它的地址,一个类型为*T的值。在Go的术语中,其返回一个指向新分配的类型为T的指针,这个指针指向的内容的值为零(zero value)。注意并非指针为零。数据结构
Go语言中的对象没有C++中的构造函数,若是用C来描述,Go中的new大概至关于:函数
T *t = (T*)malloc(sizeof(T)) memset(t, 0, sizeof(T))
其实,上面的描可能也不是很准确,也许用*t=zerovalue更准确。由于对于不一样的数据类型,零值的意义是彻底不同的。好比,对于bool类型,零值为false;int的零值为0;string的零值是空字符串:指针
b := new(bool) fmt.Println(*b) i := new(int) fmt.Println(*i) s := new(string) fmt.Println(*s)
输出:对象
false 0 ""
注意最后有一个空字符串。blog
不少时候,零值并非一个好主意,咱们须要作一些初始化。考虑以下结构体:内存
type Rect struct { x, y float64 width, height float64 }
零值的Rect并无多大用处,咱们如下方式进行初始化:字符串
rect3 := &Rect{0, 0, 100, 200} rect4 := &Rect{width: 100, height: 200}
申明一下,Go语言中没有C++中的构造函数,对象的建立通常交给一个全局的建立函数来完成:string
func NewRect(x, y, width, height float64) *Rect { return &Rect{x, y, width, height} }
内建函数make(T, args)与new(T)的用途不同。它只用来建立slice,map和channel,而且返回一个初始化的(而不是置零),类型为T的值(而不是*T)。之因此有所不一样,是由于这三个类型的背后引用了使用前必须初始化的数据结构。例如,slice是一个三元描述符,包含一个指向数据(在数组中)的指针,长度,以及容量,在这些项被初始化以前,slice都是nil的。对于slice,map和channel,make初始化这些内部数据结构,并准备好可用的值。it
例如:
make([]int, 10, 100)
分配一个有100个int的数组,而后建立一个长度为10,容量为100的slice结构,该slice引用包含前10个元素的数组。对应的,new([]int)返回一个指向新分配的,被置零的slice结构体的指针,即指向值为nil的slice的指针。
var p *[]int = new([]int) // allocates slice structure; *p == nil; rarely useful var v []int = make([]int, 100) // the slice v now refers to a new array of 100 ints // Unnecessarily complex:这种作法实在是很蛋疼 var p *[]int = new([]int) *p = make([]int, 100, 100) // Idiomatic:习惯的作法 v := make([]int, 100)
记住make只用于map,slice和channel,而且不返回指针。要得到一个显式的指针,使用new进行分配,或者显式地使用一个变量的地址。
主要参考《effective go》