2016-02-15 03:06:34 +00:00
|
|
|
|
### 2.3.3. new函数
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2017-08-24 14:25:47 +00:00
|
|
|
|
另一个创建变量的方法是调用内建的new函数。表达式new(T)将创建一个T类型的匿名变量,初始化为T类型的零值,然后返回变量地址,返回的指针类型为`*T`。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
2016-02-15 03:06:34 +00:00
|
|
|
|
p := new(int) // p, *int 类型, 指向匿名的 int 变量
|
2015-12-09 07:45:11 +00:00
|
|
|
|
fmt.Println(*p) // "0"
|
2016-02-15 03:06:34 +00:00
|
|
|
|
*p = 2 // 设置 int 匿名变量的值为 2
|
2015-12-09 07:45:11 +00:00
|
|
|
|
fmt.Println(*p) // "2"
|
|
|
|
|
```
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
用new创建变量和普通变量声明语句方式创建变量没有什么区别,除了不需要声明一个临时变量的名字外,我们还可以在表达式中使用new(T)。换言之,new函数类似是一种语法糖,而不是一个新的基础概念。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
下面的两个newInt函数有着相同的行为:
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
2016-01-18 04:14:26 +00:00
|
|
|
|
func newInt() *int {
|
|
|
|
|
return new(int)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newInt() *int {
|
|
|
|
|
var dummy int
|
|
|
|
|
return &dummy
|
|
|
|
|
}
|
2015-12-09 07:45:11 +00:00
|
|
|
|
```
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
每次调用new函数都是返回一个新的变量的地址,因此下面两个地址是不同的:
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
p := new(int)
|
|
|
|
|
q := new(int)
|
|
|
|
|
fmt.Println(p == q) // "false"
|
|
|
|
|
```
|
|
|
|
|
|
2016-04-04 11:50:06 +00:00
|
|
|
|
当然也可能有特殊情况:如果两个类型都是空的,也就是说类型的大小是0,例如`struct{}`和 `[0]int`, 有可能有相同的地址(依赖具体的语言实现)(译注:请谨慎使用大小为0的类型,因为如果类型的大小为0的话,可能导致Go语言的自动垃圾回收器有不同的行为,具体请查看`runtime.SetFinalizer`函数相关文档)。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2016-04-04 11:50:06 +00:00
|
|
|
|
new函数使用通常相对比较少,因为对于结构体来说,直接用字面量语法创建新变量的方法会更灵活(§4.4.1)。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
由于new只是一个预定义的函数,它并不是一个关键字,因此我们可以将new名字重新定义为别的类型。例如下面的例子:
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
func delta(old, new int) int { return new - old }
|
|
|
|
|
```
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
由于new被定义为int类型的变量名,因此在delta函数内部是无法使用内置的new函数的。
|