golang學習筆記7:指標
不像 Java 和 .NET,Go 語言為程式員提供了控制資料結構的指標的能力;但是,你不能進行指標運算。通過給予程式設計師基本記憶體佈局,Go 語言允許你控制特定集合的資料結構、分配的數量以及記憶體訪問模式,這些對構建執行良好的系統是非常重要的:指標對於效能的影響是不言而喻的,而如果你想要做的是系統程式設計、作業系統或者網路應用,指標更是不可或缺的一部分。
程式在記憶體中儲存它的值,每個記憶體塊(或字)有一個地址,通常用十六進位制數表示,如:0x6b0820 或 0xf84001d7f0。
Go 語言的取地址符是 &,放到一個變數前使用就會返回相應變數的記憶體地址。
下面的程式碼片段可能輸出 An integer: 5, its location in memory: 0x6b0820(這個值隨著你每次執行程式而變化)。
var i1 = 5
fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)
這個地址可以儲存在一個叫做指標的特殊資料型別中,在本例中這是一個指向 int 的指標,即 i1:此處使用 *int 表示。如果我們想呼叫指標 intP,我們可以這樣宣告它:
var intP *int 然後使用 intP = &i1 是合法的,此時 intP 指向 i1。
package main
import "fmt"
func main() {
var i1 = 5
fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1)
var intP *int;
intP = &i1;
fmt.Printf("The value at memory location %p is %d\n", intP, *intP)}
輸出: An integer: 5, its location in memory: 0x24f0820 The value at memory location 0x24f0820 is 5
Go 語言和 C、C++ 以及 D 語言這些低階(系統)語言一樣,都有指標的概念。
但是對於經常導致 C 語言記憶體洩漏繼而程式崩潰的指標運算
(所謂的指標演算法,如: pointer+2 ,移動指標指向字串的位元組數或陣列的某個位置)
是不被允許的。Go 語言中的指標保證了記憶體安全,更像是 Java、C# 和 VB.NET 中的引用。
因此 c = *p++ 在 Go 語言的程式碼中是不合法的。指標的一個高階應用是你可以傳遞一個變數的引用(如函式的引數),這樣不會傳遞變數的拷貝。指標傳遞是很廉價的,只佔用 4 個或 8 個位元組。當程式在工作中需要佔用大量的記憶體,或很多變數,或者兩者都有,使用指標會減少記憶體佔用和提高效率。被指向的變數也儲存在記憶體中,直到沒有任何指標指向它們,所以從它們被建立開始就具有相互獨立的生命週期。
另一方面(雖然不太可能),由於一個指標導致的間接引用(一個程序執行了另一個地址),指標的過度頻繁使用也會導致效能下降。
指標也可以指向另一個指標,並且可以進行任意深度的巢狀,導致你可以有多級的間接引用,但在大多數情況這會使你的程式碼結構不清晰。
如我們所見,在大多數情況下 Go 語言可以使程式設計師輕鬆建立指標,並且隱藏間接引用,如:自動反向引用。對一個空指標的反向引用是不合法的,並且會使程式崩潰。
