本文摘自php中文网,作者青灯夜游,侵删。
区别:在go语言中,make和new都是内存的分配(堆上),但是make只用于slice、map以及channel的初始化(非零值);而new用于类型的内存分配,并且内存置为零。make返回的是引用类型本身;而new返回的是指向类型的指针。
本文操作环境:Windows10系统、GO 1.11.2、thinkpad t480电脑。
相关推荐:《go教程》
Go语言中new和make都是用来内存分配的原语(allocation primitives)。简单的说,new只分配内存,make用于slice,map,和channel的初始化。
new
new(T)函数是一个分配内存的内建函数。
我们都知道,对于一个已经存在变量,可对其指针进行赋值。
示例
1 2 3 4 5 | var p int
var v *int
v = &p
*v = 11
fmt.Println(*v)
|
那么,如果不是已经存在的变量会如何呢?能对其直接赋值吗?
示例
1 2 3 | var v *int
*v = 8
fmt.Println(*v)
|
结果会报如下错误
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x48df66]
如何解决?通过Go提供了new来初始化一地址就可以解决。
1 2 3 4 | var v *int
v = new (int)
*v = 8
fmt.Println(*v)
|
那么我们来分析一下
1 2 3 4 5 6 | var v *int
fmt.Println(*v)
fmt.Println(v)
v = new (int)
fmt.Println(*v)
fmt.Println(v)
|
我们可以看到初始化一个指针变量,其值为nil,nil的值是不能直接赋值的。通过new其返回一个指向新分配的类型为int的指针,指针值为0xc00004c088,这个指针指向的内容的值为零(zero value)。
同时,需要注意的是不同的指针类型零值是不同的。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | type Name struct {
P string
}
var av *[5]int
var iv *int
var sv *string
var tv *Name
av = new ([5]int)
fmt.Println(*av)
iv = new (int)
fmt.Println(*iv)
sv = new (string)
fmt.Println(*sv)
tv = new (Name)
fmt.Println(*tv)
|
上面讲了对普通类型new()处理过后是如何赋值的,这里再讲一下对复合类型(数组,slice,map,channel等),new()处理过后,如何赋值。
数组示例
1 2 3 4 5 6 | var a [5]int
fmt.Printf( "a: %p %#v \n" , &a, a)
av := new ([5]int)
fmt.Printf( "av: %p %#v \n" , &av, av)
(*av)[1] = 8
fmt.Printf( "av: %p %#v \n" , &av, av)
|
silce 示例
1 2 3 4 5 6 | var a *[]int
fmt.Printf( "a: %p %#v \n" , &a, a)
av := new ([]int)
fmt.Printf( "av: %p %#v \n" , &av, av)
(*av)[0] = 8
fmt.Printf( "av: %p %#v \n" , &av, av)
|
map 示例
1 2 3 4 5 6 | var m map[string]string
fmt.Printf( "m: %p %#v \n" , &m, m)
mv := new (map[string]string)
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
(*mv)[ "a" ] = "a"
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
|
channel示例
1 2 3 | cv := new (chan string)
fmt.Printf( "cv: %p %#v \n" , &cv, cv)
|
通过上面示例我们看到数组通过new处理,数组av初始化零值,数组虽然是复合类型,但不是引用类型,其他silce、map、channel类型也属于引用类型,go会给引用类型初始化为nil,nil是不能直接赋值的。并且不能用new分配内存。无法直接赋值。那么用make函数处理会是怎么样呢?
make
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | av := make([]int, 5)
fmt.Printf( "av: %p %#v \n" , &av, av)
av[0] = 1
fmt.Printf( "av: %p %#v \n" , &av, av)
mv := make(map[string]string)
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
mv[ "m" ] = "m"
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
chv := make(chan string)
fmt.Printf( "chv: %p %#v \n" , &chv, chv)
go func(message string) {
chv <- message
}( "Ping!" )
fmt.Println(<-chv)
close(chv)
|
make不仅可以开辟一个内存,还能给这个内存的类型初始化其零值。
它和new还能配合使用
示例
1 2 3 4 5 6 7 | var mv *map[string]string
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
mv = new (map[string]string)
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
(*mv) = make(map[string]string)
(*mv)[ "a" ] = "a"
fmt.Printf( "mv: %p %#v \n" , &mv, mv)
|
通过new给指针变量mv分配了一个内存,并赋予其内存地址。Map是引用类型,其零值为nil,使用make初始化 map,然后变量就能使用*
给指针变量mv赋值了。
小结:
- make和new都是golang用来分配内存的內建函数,且在堆上分配内存,make 即分配内存,也初始化内存。new只是将内存清零,并没有初始化内存。
- make返回的还是引用类型本身;而new返回的是指向类型的指针。
- make只能用来分配及初始化类型为slice,map,channel的数据;new可以分配任意类型的数据。
更多编程相关知识,请访问:编程教学!!
以上就是go语言中make和new的区别是什么?的详细内容,更多文章请关注木庄网络博客!!
相关阅读 >>
Go语言中函数与方法介绍
Go语言向函数传递数组
Go语言 goto 语句
Go语言适合做什么?
Go语言 if 语句嵌套
Go语言 if…else 语句
yum怎么安装Go语言
Go语言是什么开源协议
Go语言函数引用传递值
Go语言能做web吗
更多相关阅读请进入《Go语言》频道 >>
老貘
一个与时俱进的Go编程知识库。
转载请注明出处:木庄网络博客 » go语言中make和new的区别是什么?