2015-12-26 07:42:56 +00:00
|
|
|
|
### 2.3.3. new函數
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2015-12-26 07:42:56 +00:00
|
|
|
|
另一個創建變量的方法是調用用內建的new函數。表達式new(T)將創建一個T類型的匿名變量,初始化爲T類型的零值,然後返迴變量地址,返迴的指針類型爲`*T`。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
2015-12-18 02:53:03 +00:00
|
|
|
|
p := new(int) // p, *int 類型, 指向匿名的 int 變量
|
2015-12-09 07:45:11 +00:00
|
|
|
|
fmt.Println(*p) // "0"
|
2015-12-18 02:53:03 +00:00
|
|
|
|
*p = 2 // 設置 int 匿名變量的值爲 2
|
2015-12-09 07:45:11 +00:00
|
|
|
|
fmt.Println(*p) // "2"
|
|
|
|
|
```
|
|
|
|
|
|
2016-01-18 03:22:04 +00:00
|
|
|
|
用new創建變量和普通變量聲明語句方式創建變量沒有什麽區别,除了不需要聲明一個臨時變量的名字外,我們還可以在表達式中使用new(T)。換言之,new函數類似是一種語法糖,而不是一個新的基礎概念。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2015-12-26 07:42:56 +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
|
|
|
|
```
|
|
|
|
|
|
2015-12-26 07:42:56 +00:00
|
|
|
|
每次調用new函數都是返迴一個新的變量的地址,因此下面兩個地址是不同的:
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
p := new(int)
|
|
|
|
|
q := new(int)
|
|
|
|
|
fmt.Println(p == q) // "false"
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-26 07:42:56 +00:00
|
|
|
|
當然也可能有特殊情況:如果兩個類型都是空的,也就是説類型的大小是0,例如`struct{}`和 `[0]int`, 有可能有相同的地址(依賴具體的語言實現)(譯註:請謹慎使用大小爲0的類型,因爲如果類型的大小位0好話,可能導致Go語言的自動垃圾迴收器有不同的行爲,具體請査看`runtime.SetFinalizer`函數相關文檔)。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2015-12-26 07:42:56 +00:00
|
|
|
|
new函數使用常見相對比較少,因爲對應結構體來説,可以直接用字面量語法創建新變量的方法會更靈活(§4.4.1)。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
2015-12-26 07:42:56 +00:00
|
|
|
|
由於new隻是一個預定義的函數,它併不是一個關鍵字,因此我們可以將new名字重新定義爲别的類型。例如下面的例子:
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
func delta(old, new int) int { return new - old }
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-26 07:42:56 +00:00
|
|
|
|
由於new被定義爲int類型的變量名,因此在delta函數內部是無法使用內置的new函數的。
|
2015-12-09 07:45:11 +00:00
|
|
|
|
|