go语言中new和make有什么区别?

分类:编程技术 时间:2024-02-20 15:31 浏览:0 评论:0
0
这篇文章主要讲解《Go语言中new和make有什么区别》,感兴趣的朋友不妨看一下。文章介绍的方法简单、快捷、实用。让小编带你学习“go语言中new和make有什么区别”!

new()和make()的区别

以下摘录为来自https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/07.2.md

两者都在堆上分配内存,但不同类型的行为不同。

new(T)为每个新类型T分配一块内存,初始化为0并返回类型*T的内存地址:该方法返回一个指向类型T的指针,值为指向0地址的指针,适用于数组、结构体等值类型;它相当于&T{}。 make(T)返回类型T的初始值,仅适用于三种内置引用类型:slice、map和channel

也就是说,new函数分配内存,make函数初始化;下图展示了区别:

我的理解是new返回的是一个指向变量的指针,但是这个指针指向null。您无法直接访问指针。执行该操作,否则会报错,除非将指针指向该类型变量的地址。
make 返回该类型的变量,以切片变量为例。上面提到,make适合创建切片、贴图和通道,但也可以创建new

package mainimport "fmt"func main() {//使用make创建切片并返回变量本身 s1 := make([]int,5,10)fmt.Printf("use make create slise type %T value %v \n",s1, s1)s1[0] = 123s1[4] = 321fmt.Printf ("make s1 type %T value %v \n",s1,s1)//#使用new创建切片,并返回切片变量的指针s2: = new([]int)fmt.Printf("使用新创建te slise type %T value %v \n",s2,s2)fmt.Printf("new s2 type %T value %v \n",*s2,*s2)//如果要赋值的话需要使用 *dereference //虽然这里不会报语法错误,但是如果尝试直接使用 (* If s2)[0] = 123 ,就会出现运行时错误, //panic:runtimeerror:indexoutofranges2 = &s1 //需要将变量指针指向该类型变量的地址 (*s2)[0] = 123( *s2)[4] = 3211fmt.Printf("new s2 type %T value %v \n",s2,s2)//s2的修改也会影响s1fmt.Printf("s1 type %T value %v \n ",s1,s1)m1 := make(map[string]string)m1[" name"] = "yangyanxing"m1["age"] = "30"fmt.Printf("m1 使用 make create type:%T value %v \n",m1,m1)m2 := new(map[string] string)fmt.Printf("m2 use new create type:%T value %v \n",m2,m2)//直接赋值会报panic:赋值给nil中的mapm2 = &m1(*m2)["name "] = "fan"//对m2的修改也会影响m1fmt.Printf("after m2 change m1 value is %v", m1)}

输出结果为

use make create slise type []int value [0 0 0 0 0]make s1 type []int value [123 0 0 0 321] use new create slise type *[]int value &[]new s2 type [ ]int value []new s2 type *[]int value&[123 0 0 0 3211]s1 type []int value [123 0 0 0 3211]m1 use make create type:map[string]string value map[名称:yangyanxing [年龄:30]m2 使用新创建类型:*map [string]字符串值&map[]m2更改后m1值为map[name:粉丝年龄:30]

地图初始化

map有以下两种初始化方法

使用make函数

直接使用map初始化

package mainimport "fmt"func main() {//使用make初始化mapmp2:= make(map[string]string )mp2["name"] = "yangyanxing"mp2["age"] = "18"fmt.Println("m2地址",&mp2)// out:m2地址&map[name:yangyanxingage:18]mp3 := map[string]int{} //这里必须有{}。如果大括号内没有内容,则表示已经初始化了一个空字典。 mp3["yang"] = 18mp3["fan"] = 20fmt.Println(mp3)// out:map[yang:18 fan:20]mp4 := map[string]int{"yang":20,"fan":21, //最后一个也要有逗号}fmt.Println(mp4) //out:map[yang:20 fan:21]mp5 := map[string]int{"yang":30} //同一行写时无需加逗号 fmt.Println(mp5)//out: map[yang :30]mp6 : = make(map[string]int,1) //也可以给map添加一个容量mp6["yang"] = 30fmt.Println("mp6镜头为",len(mp6),"地址:",&mp6 )//out:mp6镜头为1 地址: &map[yang:30]mp6["fan"] = 31fmt.Println("mp6镜头为",len(mp6),"地址:",&mp6)//out: mp6镜头为2地址:&map[yang:30 fan:31]//new也可以用,但是不能直接赋值,因为它返回空指针 //之前需要指向该类型的变量地址operation mp7 := new(map[string]int)fmt.Println(mp7) //out:&map[]//(*mp7)["yang"] = 100 //会报运行时错误 mp7 = &mp6/ /mp7["fan"] = 1000 //MP7不能直接使用,需要先使用*解引用 (*mp7)["yang"] = 100 //此时不会报运行时错误d fmt.Println(mp7)//out:&map[yang:100 fan:31]}

切片slice的初始化

也可以通过make和切片本身进行初始化

package mainimport "fmt"func main() {//使用make初始化切片,需要传入A len长度,容量cap可选 //如果不传则长度和容量为同样的 sls1 := make([]int,5,10)sls1[0] = 100//追加到最后,这个有点意思 sls1 =append(sls1,200)//... 三个点,语法go中的sugar,展开前一个切片 sls1 =append(sls1,[]int{30,40}...)fmt.Println(sls1, len(sls1),cap(sls1))//out: [100 0 0 0 0 200 30 40]8 10sls1 =append(sls1,3,4,6)//超过切片原有容量后,会发生扩容 fmt.Println(sls1,len(sls1),cap(sls1))/ /out: [100 0 0 0 0 200 30 40 3 4 6] 11 20sls2 := make([]int,3)sls2[1] = 123fmt.Println(sls2,len(sls2),cap(sls2))/ /out: [0 123 0] 3 3//直接初始化 sls3:= []int{}sls3 =append(sls3,10,20)fmt.Println(sls3,len(sls3),cap(sls3))//出去: [10 20] 2 2sls4 := []int{1,2,3}sls5 :=[]int{1,2,5,//这里的逗号不能省略}fmt.Println(sls4,sls5)//out : [1 2 3] [1 2 5]//使用new创建切片。和map一样,返回的是指针,不能直接操作//需要先指向一个变量的地址 sls6:= new([]int)fmt.Println(sls6 )//out: &[]sls6 = &sls4fmt.Println(sls6) //out: &[1 2 3]}

数组 array 的初始化

数组不能使用 make 初始化,但可以使用 new 初始化

package mainimport "fmt" type person struct {name stringage int}func main() {fmt.Println("数组的初始化")//声明并初始化一个空数组,里面的元素值为零值of type arr1 := [2]int{}fmt.Println(arr1) //out: [0 0]//初始化时写入元素值arr2 := [2]int{1 ,3}fmt.Println(arr2 ) //out: [1 3]//只写1,否则为零值 arr3 := [2]int{1}fmt.Println(arr3) //out: [ 1 0]//arr4 := make([ 2]int) //数组不能使用makevar arr5 [2]intarr5[0]= 100fmt.Println(arr5)//[100 0]//不指定数组大小,使用...三个点让其自动扩展并计算 arr6:= [...]int{2,4, 6,8}fmt .Println(arr6,len(arr6))//out: [2 4 6 8] 4//使用new创建数组,并得到一个指针 arr7 := new([3]int)fmt .Println(arr7) //out: &[0 0 0]//可以直接操作指针 arr7[0] = 3//与使用*解引用(*arr7)[1] = 4fmt效果相同。 Println(arr7) //out : &[3 4 0]}

struct结构体初始化

结构体不能使用make,需要使用new和结构体本身

package mainimport " fmt"type person struct {name stringage int}func main() {fmt.Println("结构体初始化")//使用new返回结构体指针 stru1 := new(person)fmt. Println(stru1)// out &{ 0},默认为字段零值 //可以直接使用这个指针操作变量 //效果与使用 * dereference stru1.name = "yangyanxing" 相同(*stru1).age = 18fmt.Println(stru1,*stru1) //&{yangyanxing 18} {yangyanxing 18}//只指定一个字段,不指定默认零值 stru2 := person{name:"fan"}fmt.Println(stru2) //{fan 0 } //全部指定,字段顺序不需要按照定义的顺序 stru3 := person{age:18,name:"yang"}fmt.Println(stru3) //{yang 18}//初始化按照结构体的顺序,此时元素的值必须全写 stru4 := person{"fan",17}fmt.Println(stru4) //{fan 17}}

就是这样,相信大家对“Go语言中new和make有什么区别”有了更深入的了解了?你不妨也来实践一下吧!这是网站。更多相关内容,您可以进入相关渠道进行查询。关注我们并继续学习!

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > go语言中new和make有什么区别?

用户评论