“new”和”make”之间有什么区别?

huangapple go评论79阅读模式
英文:

What is the difference between new and make?

问题

New不会初始化内存,它只会将其清零。它返回一个指向新分配的零值的指针。

Make只能用于创建切片、映射和通道,并且它返回的是已初始化的对象。

在这个上下文中,“初始化”是什么意思?
newmake之间还有哪些其他区别?

英文:

New does not initialize the memory, it only zeros it. It returns a pointer to a newly allocated zero value.

Make creates slices, maps, and channels only, and it returns them initialized.

What does "initialized" mean in this context?
What other differences are there between new and make?

答案1

得分: 31

创建切片、映射和通道中所述:

内置函数make接受一个类型T,该类型必须是切片、映射或通道类型,可选地跟随类型特定的表达式列表。
它返回一个类型为T的值(而不是*T)。
内存的初始化如初始值一节所述。

例如,对于切片类型

make([]T, length, capacity)

产生与分配数组并对其进行切片相同的切片,因此这两个表达式是等价的:

make([]int, 50, 100)
new([100]int)[0:50]

因此,在这里,make创建了切片,并根据所使用的类型的零值进行初始化(这里是int,所以是'0')。

您可以在Go:为什么要使用make()或new()?中了解更多关于保持newmake分开的原因。


Dave Cheney刚刚写了一篇很好的文章:“Go既有make函数又有new函数,这是怎么回事?

虽然make创建了通用的切片映射通道值,但它们仍然只是普通的值;make不返回指针值

如果删除new,而使用make,那么如何构造一个指向初始化值的指针?

使用new来构造指向切片映射通道零值指针,这在当前是可行的,并且与new的行为一致。

对于它们可能引起的混淆,makenew是一致的;

  • make只创建切片、映射和通道,
  • new只返回指向初始化内存的指针。
英文:

As mentioned in Making slices, maps and channels:

>The built-in function make takes a type T, which must be a slice, map or channel type, optionally followed by a type-specific list of expressions.
It returns a value of type T (not *T).
The memory is initialized as described in the section on initial values.

For instance, for Slice type

make([]T, length, capacity)

> produces the same slice as allocating an array and slicing it, so these two expressions are equivalent:

make([]int, 50, 100)
new([100]int)[0:50]

So here, make creates the slice, and initialize its content depending on the zero value if the type used (here int, so '0')

You can see more about the need of keeping new and make separate in Go: why would I make() or new()?


Dave cheney just wrote a good article: "Go has both make and new functions, what gives ?"

> Although make creates generic slice, map, and channel values, they are still just regular values; make does not return pointer values.

> If new was removed in favour make, how would you construct a pointer to an initialised value ?

> Using new to construct a pointer to a slice, map, or channel zero value works today and is consistent with the behaviour of new.

> For the confusion they may cause, make and new are consistent;

> - make only makes slices, maps, and channels,

  • new only returns pointers to initialised memory.

答案2

得分: 12

首先,它们的第一个区别是类型:make(T, ...) 总是返回类型 T,而 new(T, ...) 总是返回类型 *T。这告诉你它们非常不同。

new 适用于所有类型,并动态分配该类型的变量的空间,将其初始化为该类型的零值,并返回指向它的指针。

一种思考方式是

result = new(T)

始终等同于

var temp T
result = &temp

换句话说,你可以通过定义给定类型的变量、不初始化它,然后取其指针来完成与 new 相同的操作。

make 在某些内置类型(切片、映射或通道)中充当一种“构造函数”的角色。

英文:

First difference is type: make(T, ...) always returns type T, whereas new(T, ...) always returns type *T. That tells you that they are very different.

new works for all types, and dynamically allocates space for a variable of that type, initialized to the zero value of that type, and returns a pointer to it.

One way to think of it is that

result = new(T)

is always equivalent to

var temp T
result = &temp

(in other words you can do the same thing that new does by defining a variable of the given type, not initializing it, and then taking a pointer to it.)

make works as a kind of "constructor" for certain built-in types (slice, map, or channel).

答案3

得分: 6

内置的new(T)函数为类型为T的新项目分配“零值”存储空间,并返回其地址,即*T类型的值。在Go术语中,它返回指向新分配的类型T的零值的指针。例如,以下是创建指向零值bytes.Buffer的指针p的三种不同方式,它们是等效的:

// 分配足够的内存来存储bytes.Buffer值
// 并返回指向该值地址的指针。
var buf bytes.Buffer
p := &buf

// 使用复合字面量执行分配
// 并返回指向该值地址的指针。
p := &bytes.Buffer{}

// 使用new函数执行分配,它将
// 返回指向该值地址的指针。
p := new(bytes.Buffer)

另一方面,make()函数是一个特殊的内置函数,用于初始化切片、映射和通道。请注意,make()只能用于初始化切片、映射和通道,并且与new()函数不同,make()不返回指针。

切片、映射和通道也可以使用复合字面量表达式进行初始化,以及使用make()。下面是两种不同(但等效)的初始化映射m的方式,该映射将字符串键映射到布尔值:

// 使用make()初始化映射。
m := make(map[string]bool, 0)

// 使用复合字面量初始化映射。
m := map[string]bool{}

// 您还可以使用复合字面量和初始数据初始化映射,
// 如下所示:
m := map[string]bool{
"java": false,
"go": true,
}

英文:

“new”和”make”之间有什么区别?
The builtin new(T) function allocates “zeroed” storage for a new item of type T and returns its address, a value of type *T. In Go terminology, it returns a pointer to a newly allocated zero value of type T. For example, here are three different ways to create a pointer p that points to a zeroed bytes.Buffer value, each of which are equivalent:

// Allocate enough memory to store a bytes.Buffer value
// and return a pointer to the value's address.
var buf bytes.Buffer
p := &buf

// Use a composite literal to perform allocation and
// return a pointer to the value's address.
p := &bytes.Buffer{}

// Use the new function to perform allocation, which will
// return a pointer to the value's address.
p := new(bytes.Buffer)

The make() function, on the other hand, is a special built-in function that is used to initialize slices, maps, and channels. Note that make() can only be used to initialize slices, maps, and channels, and that, unlike the new() function, make() does not return a pointer.

Slices, maps, and channels can also be initialized using a composite literal expressions, as well as with make(). Two different (yet equivalent) ways to initialize a map m which maps string keys to bool values are given below as examples:

// Using make() to initialize a map.
m := make(map[string]bool, 0)

// Using a composite literal to initialize a map.
m := map[string]bool{}

// You can also initialize maps with initial data using a composite literal,
// as shown below:
m := map[string]bool{
    "java": false,
    "go":   true,
}

huangapple
  • 本文由 发表于 2014年8月18日 15:22:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/25358130.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定