Go new vs make

原创
2018/08/31 18:58
阅读数 47

摘要

Go 提供了两个关键字newmake 来为类型分配内存,但两者的功能是不同的,一句话来说就是:new只管 内存分配,而make用来初始化slice,map 和 channel

new

原型:func new(Type) *Type

Go 官方文档上的解释:

The new built-in function allocates memory. The first argument is a type,
not a value, and the value returned is a pointer to a newly
allocated zero value of that type.

这里我们关注到一点 newly allocated zero value of that type, 也就是说new 分配内存之后,会返回对应类型为零值的指针,它的参数是一个类型,这个类型在这里是一个占位符,可以看到它的定义为type Type int , 我们在应用程序里是获取不到的(一直在这有疑惑,Go 的包规范要求首字母大写的是public的,小写的是private的,但是在builtin 包中,小写的可以在程序中使用,大写的反而是不可用的)。

make

原型:func make(t Type, size ...IntegerType) Type

Go 官方文档解释:

The make built-in function allocates and initializes an object of type
slice, map, or chan (only). Like new, the first argument is a type, not a
value. Unlike new, make's return type is the same as the type of its
argument, not a pointer to it. The specification of the result depends on
the type:

make 只能用来创建 slice,map 和channel,并不能用于其他类型,当然我们可以看到 make 和 new 的函数签名是类似的,但是当使用 int 等类型作为 make 参数时,编译会报错。

make还可以接收整形参数来决定初始容量,slice 第一个参数代表len,第二个代表 capacity,map 只能有一个参数代表初始容量,channel 的 int 参数代表 buffer 大小(没有代表无缓冲)

为什么需要用 make 来创建这三个类型?因为这三个类型代表的是对数据结构的引用,要使用它们,必须要先初始化。以slice 为例,一个 slice 需要3 个元素:指向数据的指针,长度(len)和容量(cap)(有疑问的可以参见 go slice usage), 在未初始化之前slice 为nil,是不可用的。也就是说 对slice、map、channel 三种类型,make初始化了它们的内部数据结构,使得它们立即可用。

对比

new 对于接收的参数类型是没有限制的,也即我们可以传slice、map、channel类型,表面上看new 的存在就够了,但是,我们要知道,这个new 出来的slice、map、channel 为nil,实际上没有用处,对于接口也一样,new 可以接收,但返回 nil,在程序中是不可用的。

为何要有两个函数

这个问题在网上也有很多讨论,问题的真正答案只有 Go 语言的发明人才能给出。我们这里只作猜测。

与这个问题对等的是如果只有一个分配函数会怎么样?

假设我们的新分配函数名字叫alloc, 参数只能与 make 一样,因为我们既需要能处理 int 这种不需要长度的类型,也需要处理 slice 这种需要长度的类型,然后返回类型为指针(只能有一种返回类型,分配到堆上返回指针),我们来看一下它的使用问题。

  1. 参数冗余

size ...IntegerType 参数在为基本类型时是多余的,就算传递了,也是不用的,这是一种设计缺陷。按照我们在其他编程语言里的编程实践,遇到这种问题时,我们会使用方法重载,但 Go 中不支持函数重载,此路不通。

  1. 返回类型为指针,slice等使用麻烦

使用 make 返回的是类型本身,如果返回的是指针的话,我们使用起来就需要多加一层括号,获取 slice 中的某一个元素需要这样使用(*slice)[i], map 也是一样,会引起不必要的解引用

从语言设计者的角度来看,设计一个函数槽点太多,索性分开为两个,权责明确,使用方便,而且这不又给了很多人写博客的一个话题嘛。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部