Golang new() vs make()

对于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()返回的是指针。

原文地址:https://www.cnblogs.com/DillGao/p/6524913.html