gopl-zh.github.com/ch2/ch2-03-3.md

1.9 KiB
Raw Blame History

2.3.3. new函数

另一个创建变量的方法是调用内建的new函数。表达式new(T)将创建一个T类型的匿名变量初始化为T类型的零值然后返回变量地址返回的指针类型为*T

p := new(int)   // p, *int 类型, 指向匿名的 int 变量
fmt.Println(*p) // "0"
*p = 2          // 设置 int 匿名变量的值为 2
fmt.Println(*p) // "2"

用new创建变量和普通变量声明语句方式创建变量没有什么区别除了不需要声明一个临时变量的名字外我们还可以在表达式中使用new(T)。换言之new函数类似是一种语法糖而不是一个新的基础概念。

下面的两个newInt函数有着相同的行为

func newInt() *int {
	return new(int)
}

func newInt() *int {
	var dummy int
	return &dummy
}

每次调用new函数都是返回一个新的变量的地址因此下面两个地址是不同的

p := new(int)
q := new(int)
fmt.Println(p == q) // "false"

当然也可能有特殊情况如果两个类型都是空的也就是说类型的大小是0例如struct{}[0]int有可能有相同的地址依赖具体的语言实现译注请谨慎使用大小为0的类型因为如果类型的大小为0的话可能导致Go语言的自动垃圾回收器有不同的行为具体请查看runtime.SetFinalizer函数相关文档)。

new函数使用通常相对比较少因为对于结构体来说直接用字面量语法创建新变量的方法会更灵活§4.4.1)。

由于new只是一个预定义的函数它并不是一个关键字因此我们可以将new名字重新定义为别的类型。例如下面的例子

func delta(old, new int) int { return new - old }

由于new被定义为int类型的变量名因此在delta函数内部是无法使用内置的new函数的。