介绍文档用了很多段落来解释new()和make()之间的区别,但实际上,您可以在局部范围内创建对象并返回它们。

为什么要使用这对分配器?


当前回答

new(T):它返回一个指向类型T的指针,一个类型为*T的值,它分配并归零内存。new(T)等价于&T{}。

make(T):返回类型为T的初始化值,分配并初始化内存。它用于切片,映射和通道。

其他回答

Go有多种内存分配和值初始化的方式:

科技{…}, &someLocalVar, new, make

在创建复合字面量时也可以进行分配。


New可用于分配整数等值,&int是非法的:

new(Point)
&Point{}      // OK
&Point{2, 3}  // Combines allocation and initialization

new(int)
&int          // Illegal

// Works, but it is less convenient to write than new(int)
var i int
&i

new和make的区别可以从下面的例子中看出:

p := new(chan int)   // p has type: *chan int
c := make(chan int)  // c has type: chan int

假设Go没有new和make,但它有内置函数new。然后示例代码看起来像这样:

p := NEW(*chan int)  // * is mandatory
c := NEW(chan int)

*是强制性的,所以:

new(int)        -->  NEW(*int)
new(Point)      -->  NEW(*Point)
new(chan int)   -->  NEW(*chan int)
make([]int, 10) -->  NEW([]int, 10)

make(Point)  // Illegal
make(int)    // Illegal

是的,可以将new和make合并为一个内置函数。然而,一个内置函数可能比两个内置函数更容易让新程序员感到困惑。

考虑到以上几点,new和make保持分离似乎更合适。

您需要make()来创建通道和映射(以及切片,但这些也可以从数组创建)。没有其他方法来创建这些,所以不能从词典中删除make()。

至于new(),当可以使用结构语法时,我不知道为什么还需要它。但它确实有一个独特的语义含义,即“创建并返回一个将所有字段初始化为零值的结构体”,这很有用。

new(T):它返回一个指向类型T的指针,一个类型为*T的值,它分配并归零内存。new(T)等价于&T{}。

make(T):返回类型为T的初始化值,分配并初始化内存。它用于切片,映射和通道。

你能用它做的事情用其他方法做不到:

创建通道 创建一个预分配空间的映射 创建一个预先分配空间的切片,或者使用len != cap

要证明新的合理性有点难。它简化的主要事情是创建指向非复合类型的指针。 下面两个函数是等价的。一个更简洁一点:

func newInt1() *int { return new(int) }

func newInt2() *int {
    var i int
    return &i
}

除了在Effective Go中解释的所有内容外,new(T)和&T{}之间的主要区别是后者显式执行堆分配。但是,应该注意的是,这取决于实现,因此可能会发生变化。

比较make和new没有什么意义,因为两者执行完全不同的功能。但这在链接的文章中有详细的解释。