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

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


当前回答

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保持分离似乎更合适。

其他回答

new(T) - Allocates memory, and sets it to the zero value for type T.. ..that is 0 for int, "" for string and nil for referenced types (slice, map, chan) Note that referenced types are just pointers to some underlying data structures, which won't be created by new(T) Example: in case of slice, the underlying array won't be created, thus new([]int) returns a pointer to nothing make(T) - Allocates memory for referenced data types (slice, map, chan), plus initializes their underlying data structures Example: in case of slice, the underlying array will be created with the specified length and capacity Bear in mind that, unlike C, an array is a primitive type in Go!


话虽如此: make(T)的行为类似于复合文字语法 new(T)的行为类似于var(当变量未初始化时)

func main() {
    fmt.Println("-- MAKE --")
    a := make([]int, 0)
    aPtr := &a
    fmt.Println("pointer == nil :", *aPtr == nil)
    fmt.Printf("pointer value: %p\n\n", *aPtr)

    fmt.Println("-- COMPOSITE LITERAL --")
    b := []int{}
    bPtr := &b
    fmt.Println("pointer == nil :", *bPtr == nil)
    fmt.Printf("pointer value: %p\n\n", *bPtr)

    fmt.Println("-- NEW --")
    cPtr := new([]int)
    fmt.Println("pointer == nil :", *cPtr == nil)
    fmt.Printf("pointer value: %p\n\n", *cPtr)

    fmt.Println("-- VAR (not initialized) --")
    var d []int
    dPtr := &d
    fmt.Println("pointer == nil :", *dPtr == nil)
    fmt.Printf("pointer value: %p\n", *dPtr)
}

运行程序

-- MAKE --
pointer == nil : false
pointer value: 0x118eff0  # address to underlying array

-- COMPOSITE LITERAL --
pointer == nil : false
pointer value: 0x118eff0  # address to underlying array

-- NEW --
pointer == nil : true
pointer value: 0x0

-- VAR (not initialized) --
pointer == nil : true
pointer value: 0x0

进一步阅读: https://golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make

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

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

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

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

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

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

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

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保持分离似乎更合适。

已经有很多很好的答案,但是让我解释一下new()和make()作为单独的分配器的必要性。

new(T)分配给定类型T的未初始化的零内存,并返回指向该内存的指针,以便它可以使用。归零仅仅意味着分配的内存中给定类型的值为零。某些go类型的零值为- Int - 0 Bool - false Float - 0 字符串- "" struct -每个成员的零值

Problem with new() arises when it needs to handle three other composite types - chan, slice and map. These three types are special in essence that their underlying type is not just an another type but rather a state that needs to be initialized. For example , the underlying state of a slice consists of a pointer to the first element of internal array storage, a length that determines number of elements that can be accessed and a capacity that increases as the number of elements grow. new() certainly cannot handle allocation of such types due to their need for extra initialization step, that is where make() come into play.

make(T, args)是专门为chan, slice和map类型创建的。它不仅分配chan、slice和map的内部存储类型,而且还初始化它们的底层状态,使它们可以使用。例如,对于片,它分配内部数组存储,设置指针指向该数组中的第一个元素,并设置长度和容量值。