Golang——new与make

/ 0评 / 0

在go中要主动把变量定义在堆上只有这两中方法,make与new,二者间的区别是非常大的。

(ps: 为何要强调是主动呢?因为go会做逃逸分析,编译器会帮你去最终哪些变量会放在堆上,因此在go中是不需要像C/C++一样关心变量的开辟位置的)


new

go中的new与其他语言中的new语义不一样,C++、Java中new会做两件事

1、分配堆上的内存

2、调用对应的构造方法

然而在go中仅仅是给你一块空间,这块空间被初始化为相应类型的零值或nil,在堆或是栈都得由编译器来做逃逸分析,也就是说new并不是非常有用,或者说几乎没必要去用。

其参数为类型,返回值为该类型的指针,指向该段被开辟内存的首地址,基本用法如下

image.png

结果

image.png

new还会把开辟的内存全部初始化为0,返回的是一个地址,之后每次使用时都要解引用指针a,而事实上我们在go中几乎不太用指针。

new可以接受一切类型

image.png

结果

image.png

我们看到,new的对于slice这样的结构性数据无能为力,因为new得到的slice其prt域还未指向具体的底层数组,不过非要在new后使用slice也是可以的,可以直接append对*arr进行操作,不过我们有专用的make,何必用new呢

当然,对于map这样内部比slice更复杂结构就更无能为力了

image.png

结果

image.png

对于chan更是没有意义,new出来的chan完全就是nil,无论读出还是写入都不可能,因此只会永久阻塞被runtime判为死锁

image.png

结果

image.png

new对于我们的引用类型是几乎没用,而其他类型本来也没必要非显示去new在堆上,因此new确实用得少


make

make同样是把内存定义在堆上,make的参数只能是引用类型

其函数签名如下

image.png

其中size对于不同的t有不同的意义

一、用于slice

image.png

结果

image.png

用于slice时可以传入最多三个参数,第一个是slice的基本类型,第二个是slice的len,第三个是slice的cap

二、用于map

image.png

结果

image.png

用于slice时只能传入一个参数,事实上可以再传入一个,但是那个参数没有任何意义,和没传没有区别

三、用于chan

image.png

结果

image.png

make用于chan的时候第二个参数用于指定chan是否带缓冲区,不过这不是本篇的重点,就不展开了


new于make的区别总结一下

new适用于任何对象,只分配内存,不构造对应类型的内部结构,因此对于引用类型几乎用不了,而make会分配内存并构造内部结构,但是只能用于引用类型

发表评论

电子邮件地址不会被公开。 必填项已用*标注