This commit is contained in:
chai2010 2016-01-18 12:14:26 +08:00
parent e16eebfefa
commit 1a780a2a52
2 changed files with 18 additions and 9 deletions

View File

@ -14,10 +14,14 @@ fmt.Println(*p) // "2"
下面的兩個newInt函數有着相同的行爲
```Go
func newInt() *int { func newInt() *int {
return new(int) var dummy int
} return &dummy
}
func newInt() *int {
return new(int)
}
func newInt() *int {
var dummy int
return &dummy
}
```
每次調用new函數都是返迴一個新的變量的地址因此下面兩個地址是不同的

View File

@ -37,14 +37,19 @@ for t := 0.0; t < cycles*2*math.Pi; t += res {
```Go
var global *int
func f() { func g() {
var x int y := new(int)
x = 1 *y = 1
global = &x }
func f() {
var x int
x = 1
global = &x
}
func g() {
y := new(int)
*y = 1
}
```
這里的x變量必須在堆上分配因爲它在函數退出後依然可以通過包一級的global變量找到雖然它是在函數內部定義的用Go語言的術語説這個x局部變量從函數f中逃逸了。相反當g函數返迴時變量`*y`將是不可達的,也就是説可以馬上被迴收的。因此,`*y`併沒有從函數g中逃逸編譯器可以選擇在棧上分配`*y`的存儲空間譯註也可以選擇在堆上分配然後由Go語言的GC迴收這個變量的內存空間雖然這里用的是new方式。其實在任何時候你併不需爲了編寫正確的代碼而要考慮變量的逃逸行爲要記住的是逃逸的變量需要額外分配內存同時對性能的優化可能會産生細微的影響。
f函數里的x變量必須在堆上分配因爲它在函數退出後依然可以通過包一級的global變量找到雖然它是在函數內部定義的用Go語言的術語説這個x局部變量從函數f中逃逸了。相反當g函數返迴時變量`*y`將是不可達的,也就是説可以馬上被迴收的。因此,`*y`併沒有從函數g中逃逸編譯器可以選擇在棧上分配`*y`的存儲空間譯註也可以選擇在堆上分配然後由Go語言的GC迴收這個變量的內存空間雖然這里用的是new方式。其實在任何時候你併不需爲了編寫正確的代碼而要考慮變量的逃逸行爲要記住的是逃逸的變量需要額外分配內存同時對性能的優化可能會産生細微的影響。
Go語言的自動垃圾收集器對編寫正確的代碼是一個鉅大的幫助但也併不是説你完全不用考慮內存了。你雖然不需要顯式地分配和釋放內存但是要編寫高效的程序你依然需要了解變量的生命週期。例如如果將指向短生命週期對象的指針保存到具有長生命週期的對象中特别是保存到全局變量時會阻止對短生命週期對象的垃圾迴收從而可能影響程序的性能