new函数
内置的new
函数是另一种创建变量的方式。表达式new(T)
创建一个未命名的T
类型变量,初始化为T
类型的零值,并返回其地址(地址类型为*T
):
p := new(int) // p为*int类型的指针,指向未命名的int变量
fmt.Println(*p) // 输出 0,int变量的零值
*p = 2 // 把未命名的int设置为2
fmt.Println(*p) // 输出 2
使用new
创建的变量和取其地址的普通局部变量没有什么不同,只是不需要引入(和声明)一个虚拟的名字,通过new(T)
就可以直接在表达式中使用。因此new
只是语法上的便利,不是一个基础概念。例如,下面两个newInt
函数有同样的行为:
func newInt1() *int {
return new(int)
}
func newInt2() *int {
var dummy int
return &dummy
}
每一次调用new
返回一个具有唯一地址的不同变量:
p := new(int)
q := new(int)
fmt.Println(p == q) // false
这个规则有一个例外:两个变量的类型不携带任何信息且是零值,例如struct{}
或[0]int
,当前的实现里面,它们有相同的地址。
因为最常见的未命名变量都是结构体类型,它的语法比较复杂,所以new
函数使用的相对较少。
new
是一个预声明的函数,不是一个关键字,所以它可以重定义为另外的其他类型,例如:
func delta(old, new int) int {
return new - old
}
自然地,在delta
函数内部,内置的new
函数是不可用的。
new & make
make
是另一种用于创建变量的方式,不同于new
的是,它只能用于map
、slice
、chan
类型变量的声明,且返回类型是这三个类型本身,而不是它们的指针,因为这三个类型本身就是引用类型,因此没必要返回其指针。
new的特点
-
分配内存,内存里存的是对应类型的零值,不能显式初始化指定要分配的值;
-
只有一个参数,参数是分配的内存空间所存储的变量类型,Go语言的任何类型都可以是
new
的参数,如int
、数组、结构体,甚至函数类型都可以; -
返回的是指针;
make特点
-
分配和初始化内存;
-
只能用于
slice
、map
、chan
这三个类型,不能用于其他类型,如果用于slice
类型,make
函数的第2个参数表示slice
的长度,这个参数必须给值; -
返回的是原始类型,而不是指向
slice
、map
、chan
的指针;
最佳实践
-
尽量不使用new;
-
对于
slice
、map
、chan
的定义和初始化,一般使用make
函数;
参考链接
https://zhuanlan.zhihu.com/p/438542710