在Golang当中,对于常用数据结构的初始化方式,通常有2种:make跟new。这两种初始化方法用途不同,效果不同。本篇文章就来详细讲一下make和new具体都怎么用,在什么场景下会用上。
首先来看make。比起new,make所用到的场景非常特定,一般没法直接避开。我们看下面的代码例子:
1 | func TestMake(t *testing.T) { |
两个代码似乎都会初始化长度为5的“列表”m,但其实两个m的内在构造并不相同。实际上会出现如下的效果:
- TestMake构造出来长度为5,容量为10,可变长度的slice
- TestNoMake构造出来长度为5,容量为5,不可变长度的array
这就是其中的不同了,通过两种方式,实际会构造出来两种数据结构。我们常用的var m []int
方法构造出来的,其实是可变长度的slice,可以通过append添加元素。通过make,针对slice、map、channel这三个数据结构,我们可以通过make给这些数据结构实例预设大小或容量,从而能够快速容纳一部分数据。对于需要利用这些容器类数据结构,预加载数据的场景,就可以用make来操作。
而new和make则完全不同,new的作用,主要是返回某个类型的“零值”的指针。我们来看下面的两个testcase:
1 | func TestNew(t *testing.T) { |
实际上出来的是如下的效果:
- TestNew构造出来指向0(int的零值)的指针,正常打印
- TestNoNew构造出来nil指针,panic掉
可以看到,如果我们希望在某些初始化函数里,返回某些基础数据类型,或者是struct的零值的指针,用new都可以做到,无需nil检查。尤其针对struct的零值的指针,在很多场景都能够用上。随便举一个测试协议序列化的例子:
1 | // bytes.Buffer |