对于Golang的new() 和 make()的用法有些混乱,感觉这篇资料讲解较好,翻译一下,方便学习!
原文地址:http://www.godesignpatterns.com/2014/04/new-vs-make.html
本文简要阐述Go语言中内建函数new()和make()的区别,主要面向Go语言的菜鸟:-)
内建函数new(T)为一个类型T的新变量分配内存空间,值为零,并以该空间的地址作为函数的返回值,返回值类型为*T。按照Go的说法,它返回一个指针,指向新开辟的T类型的零值。例如,有三种方式建立一个指向bytes.Buffer类型值为0的指针p,结果相同:
// 分配足够的内存空间存放bytes.Buffer类型的value,返回指向value地址的指针 var buf bytes.Buffer p := &buf // 使用一个复合字面量分配内存给value,返回指向value地址的指针 p := &bytes.Buffer{} // 使用new函数实现上面的功能 p := new(bytes.Buffer)
然而,与new()不同,make()作为特殊的内建函数,被用于初始化slices、maps、channels。
值得注意的是make() 只能用于初始化slices、maps、channels。不像new()函数,make()不能返回一个指针。
slices、maps和channels使用复合字面量进行初始化或make()均可。下面以两种不同的方式(结果一样)初始化map m,m的keys为string,values为bool:
// 使用make() 初始化 一个map m := make(map[string]bool, 0) // 使用复合字面量初始化map m := map[string]bool{}
你也可以使用带有初始化数据的复合字面量初始化maps,如下所示:
m := map[string]bool{ "java": false, "go": true, }
new()的作用比较明了,make()仍然难以理解,继续看下这里https://golang.org/doc/effective_go.html#allocation_make
内建函数make(T, args)与new(T)的使用目的不同。它仅用于初始化slices、maps、channels,并返回一个初始化(非零)的T类型(不是*T)值。造成这种差异的原因是,这三种类型,表层下面,代表的是对数据结构的引用,以至于使用前必须初始化。例如,一个slice是包含三项的描述符,其中一项是一个指针,指向数据(array里面的),另外两项分别是length和capacity。直到这些项被初始化之前,slice是nil。对于slice、maps和channels,make 初始化内部数据结构,准备可用的值。举个例子:
make([]int, 10, 100)
创建一个包含100个整数的array,然后生成一个slice 结构,length为10,capacity为100, 指向array起始的10个元素。相反,new([]int)返回一个新生成的指针,零值的slice,也就是说该指针指向一个nil的slice值。
这些例子阐明了new和make的不同。
var p *[]int = new([]int) //创建一个slice结构;*p == nil;很少使用 var v []int = make([]int, 100) //slice v 引用了一个新的含有100个元素的array //费力不讨好,可以这么写: var p *[]int = new([]int) *p = make([]int, 100, 100) //地道的写法: v := make([]int, 100)
记住,make仅用于slices、maps、channels;想要获得确切的指针就用new,或者显示获取变量的地址。
=============================================================
总结一下:
1. 使用对象不同,make()只用于初始化话slices、maps、channels;
2. 返回结果不同,new()返回的是指针。