李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
GO
正文
18.Golang之make和new区别
Leefs
2022-07-07 PM
1570℃
0条
[TOC] ### 前言 ![18.Golang之make和new区别01.jpeg](https://lilinchao.com/usr/uploads/2022/07/1814292626.jpeg) 作为go中的两个内置函数,主要用来创建和分配内存,创建内存时的规则如下: 1. new只能用来分配内存; 2. make只能用于slice、map以及channel等引用类型的初始化。 ### 一、引用类型和值类型 在讲new和make的使用场景之前,先介绍一下golang中的值类型和引用类型。 + **值类型**:int、float、bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中。当使用等号`=`将一个变量的值赋给另一个变量时,如 `j = i` ,实际上是在内存中将 i 的值进行了拷贝。可以通过 `&i` 获取变量 i 的内存地址。 (struct在方法中传参时是值类型而非引用类型) + **引用类型**:特指slice、map、channel这三种预定义类型。能够通过`make()`函数创建的都是引用类型,比如`slice`和`map`,`slice`虽然看起来像数组,但是他其实是一个指向数组内存空间的一个指针类型。 **注意** - 如果方法内部会修改当前对象的字段或改变其值,需要用指针。 - 由于值传递是(内存)复制,因此,如果对象比较大,应该使用指针(地址),避免内存拷贝(值类型等变量指向内存中的值,如果有值类型变量存放大量元素,或造成内存的大量拷贝)。 ### 三、new函数 Go语言中,new函数描述如下: ```go func new(Type) *Type ``` 从上面的代码可以看出,new 函数只接受一个参数,这个参数是一个类型,并且返回一个指向该类型内存地址的指针。同时 new 函数会把分配的内存置为零,也就是类型的零值。 **示例** > 使用 new 函数来进行分配内存空间 ```go func main() { //普通值类型 var sum *int sum = new(int) //分配空间 *sum = 98 fmt.Println(*sum) //98 //数组 var n1 [5]int fmt.Printf("n1: %p %#v \n", &n1, n1)//n1: 0xc0000c0060 [5]int{0, 0, 0, 0, 0} n2 := new([5]int) fmt.Printf("n2: %p %#v \n", &n2, n2)//n2: 0xc0000ce020 &[5]int{0, 0, 0, 0, 0} (*n2)[1] = 10 fmt.Printf("n2: %p %#v \n", &n2, n2)//n2: 0xc0000ce020 &[5]int{0, 10, 0, 0, 0} //silce var s1 *[]int fmt.Printf("s1: %p %#v \n", &s1, s1) //s1: 0xc000006038 (*[]int)(nil) s2 := new([]int) fmt.Printf("s2: %p %#v \n", &s2, s2) //s2: 0xc000006040 &[]int(nil) (*s2)[0] = 8 fmt.Printf("s2: %p %#v \n", &s2, s2) //报错panic: runtime error: index out of range //map var m1 map[string]string fmt.Printf("m1: %p %#v \n", &m1, m1)//m1: 0xc000006030 map[string]string(nil) m2 := new(map[string]string) fmt.Printf("m2: %p %#v \n", &m2, m2)//m2: 0xc000006038 &map[string]string(nil) (*m2)["name"] = "Leefs" fmt.Printf("m2: %p %#v \n", &m2, m2)//报错panic: assignment to entry in nil map } ``` new 函数也能够为自定义类型分配空间,如下所示: ```go func main() { type Student struct { name string age int } var s *Student s = new(Student) //分配空间 s.name ="Leefs" fmt.Println(s) //&{Leefs 0} } ``` **new函数返回的永远是类型的指针,指针指向分配类型的内存地址** ### 四、make函数 make 也是用于内存分配的,但是和 new 不同,它只用于 chan、map 以及 slice 的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。 在Go语言中,make 函数的描述如下: ```go func make(t Type, size ...IntegerType) Type ``` 通过上面的代码可以看出 make 函数的 t 参数必须是 chan(通道)、map(字典)、slice(切片)中的一个,并且返回值也是类型本身。 **示例** ```go func main() { //silce s := make([]int, 5) fmt.Printf("s: %p %#v \n", &s, s) //s: 0xc000004078 []int{0, 0, 0, 0, 0} s[0] = 1 fmt.Printf("s: %p %#v \n", &s, s) //s: 0xc000004078 []int{1, 0, 0, 0, 0} //map m := make(map[string]string) fmt.Printf("m: %p %#v \n", &m, m) //m: 0xc000006030 map[string]string{} m["name"] = "Leefs" fmt.Printf("m: %p %#v \n", &m, m) //m: 0xc000006030 map[string]string{"name":"Leefs"} //channel c := make(chan string) fmt.Printf("c: %p %#v \n", &c, c) //c: 0xc000006038 (chan string)(0xc00004c060) go func(message string) { c <- message // 存消息 }("Hello!") fmt.Println(<-c) // 取消息 //"Hello!" close(c) } ``` make不仅可以开辟一个内存,还能给这个内存的类型初始化其零值。 注意:make 函数只用于 map,slice 和 channel,并且不返回指针。如果想要获得一个显式的指针,可以使用 new 函数进行分配,或者显式地使用一个变量的地址。 ### 总结 **Go语言中的 new 和 make 主要区别如下:** - make和new都是golang用来分配内存的內建函数,且在堆上分配内存,make 即分配内存,也初始化内存。new只是将内存清零,并没有初始化内存。 - make返回的还是引用类型本身;而new返回的是指向类型的指针。 - make只能用来分配及初始化类型为slice,map,channel的数据;new可以分配任意类型的数据。 *附参考原文链接地址* *https://www.cnblogs.com/koeln/p/15192376.html*
标签:
Golang基础
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2232.html
上一篇
17.Golang接口介绍
下一篇
19.Golang静态类型与动态类型
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
Kibana
Spark Core
MyBatisX
FileBeat
Map
容器深入研究
Java
稀疏数组
Netty
BurpSuite
Flume
散列
哈希表
Http
字符串
Java工具类
序列化和反序列化
ClickHouse
Git
nginx
Elastisearch
Filter
数据结构
前端
Golang
RSA加解密
工具
Sentinel
栈
随笔
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭