go make 与 new 关键词的区别

2022-03-23 10:15:06 +08:00
 awanganddong

网上有相当的的文章讲述,但是还是不太理解,可以通俗的讲下之间的区别吗

3035 次点击
所在节点    Go 编程语言
19 条回复
wtysos11
2022-03-23 10:20:17 +08:00
之前看到的一篇文章,讲的挺好的:[面向信仰编程_make 和 new]( https://draveness.me/golang/docs/part2-foundation/ch05-keyword/golang-make-and-new/),最开头应该算 OP 要的通俗解释吧。
cmdOptionKana
2022-03-23 10:21:41 +08:00
一句话:make 只能用于 map 、slice 、channel ,new 只能用于结构体。
fgwmlhdkkkw
2022-03-23 10:24:06 +08:00
make 是 new 的扩展,仅支持 map 、slice 和 channel 。
fgwmlhdkkkw
2022-03-23 10:25:18 +08:00
@fgwmlhdkkkw #3 不对,它没有扩展 new ,,,😓
awanganddong
2022-03-23 10:28:38 +08:00
make 关键字的作用是创建切片、哈希表和 Channel 等内置的数据结构,而 new 的作用是为类型申请一片内存空间


我是不是可以这样理解
所谓的 make 初始化就是給已经申请内存空间,一个特定的数据结构。
new 与 make 相比,缺少了所谓的初始化的过程。
mcfog
2022-03-23 10:32:51 +08:00
awanganddong
2022-03-23 10:35:13 +08:00
@cmdOptionKana 你的意思是对用的数据类型不一致
Mohanson
2022-03-23 10:36:32 +08:00
一句话概括:

new: 在调用时编译器知道你需要使用多少内存, 例如结构体, 整形或浮点型.
make: 在调用时编译器不知道你需要使用多少内存, 例如 slice, channel, map ... 这些数据结构占用的内存是运行时才能知晓的
bruce0
2022-03-23 10:36:35 +08:00
@cmdOptionKana new 只能用于结构体 new 不止可以用于结构体, 任何是指针的都可以 用 new

```
m := make(map[int]int)
m[1] = 1
a := new(map[int]int)
a = &m

fmt.Println(*a)
```

这段代码是没问题的
cmdOptionKana
2022-03-23 10:48:07 +08:00
@bruce0 可以是可以,但我觉得这类似 JavaScript 的隐性类型转换,有具体规则,但实际使用中提倡不要去研究这些细节,直接采用最佳实践。
ganbuliao
2022-03-23 10:51:38 +08:00
对普通的使用者来说只要知道一个是返回引用类型,一个是返回值类型的变量就可以了,要想更深入了解就看代码这两个方法是咋实现的呗。反正我目前还没有要看底层实现的需求。
zhijiangliu
2022-03-23 10:52:30 +08:00
1 make 用于创建内置复合类型(map, slice, channel),new 用于创建其他基础类型数据或用户自定义数据。
2 复合类型数据结构通常是一个结构体+堆内存,因此 make 的额外作用就是初始化这些数据(和指针)。从这一点看,make 的作用是申请内存,并且初始化数据。而 new 只负责申请内存,不初始化。
3 为什么 new 不会初始化,因为没有类似构造函数的概率。
4 虽然 make 是内置函数,但它并不是一个函数。golang 编译器在编译时,会根据 make 的参数类型选择相对应的运行时函数。例如 make(map[int]int), 那么就会将 make 替换成 new_map 之类的函数。

总结一下,make 用于创建内置复合类型数据,new 用于创建其他数据。
awanganddong
2022-03-23 11:19:49 +08:00
@all 谢谢诸位,我理解理解
tpkeeper
2022-03-23 11:29:00 +08:00
@mcfog 高手
guanhui07
2022-03-23 12:18:01 +08:00
make 只能用于 map 、slice 、channel ,new 只能用于结构体。
tianyou666shen
2022-03-23 14:18:39 +08:00
make: 给 slice map channel 分配内存空间,返回这个值.注意这些类型是引用类型变量
new: 常用来初始化自己定义的结构体,创建对象,返回新建对象的引用

另外 make([]string,0,5) 可以指定 slice 的长度,容量,
一开始就能估算出容量可以减少后续一次次扩容的开销
make(chan,1) 可以创建有缓冲区的 channel
jakehu
2022-03-23 21:14:43 +08:00
make 返回引用对象
new 返回指针对象
Joyreece
2022-03-24 01:42:05 +08:00
### new 、make

`**new()**` 函数用于为任何类型对象开辟内存空间的功能,其会将新开辟的内存空间设置为零值,然后返回这块内存区域的**指针**。

`**make()**` 函数仅用于 slice 、map 和 channel 类型的初始化使用,其会先开辟内存空间,然后再进行数据结构的必要的初始化(例如设置 cap 、size 等),最后返回初始化好的**实例对象本身**。

相关**官方文档:**

- new:[https://go.dev/doc/effective_go#allocation_new]( https://go.dev/doc/effective_go#allocation_new)
- make:[https://go.dev/doc/effective_go#allocation_make]( https://go.dev/doc/effective_go#allocation_make)
lizuoqiang
2022-03-24 11:39:49 +08:00
```
- make 作用于 slice 、map 、channel ,返回值是这些类型的实例
- new 作用于 array 、struct 等值类型,返回值是分配的地址的指针
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/842258

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX