徹底學會 Go 指標 -- 就要學習 Go 語言

Seekload發表於2018-12-10

什麼是指標

寫程式碼的時候,我們通過變數就可以操作儲存在記憶體中的值,進行賦值、加減運算等。大家有沒有想過,變數代表什麼呢?其實,一個變數對應一段記憶體空間,這段空間就儲存了該變數相對應型別的值。指標的值就對應變數的地址,只通過指標,就可以更新或者讀取變數的值,而不需要用到變數名。

var i int = 10      //宣告變數i,並初始化為10
var ptr *int = &i 
fmt.Println(ptr,*ptr)
// 0xc000018060 10  指標變數ptr儲存的是i地址,*ptr對應指標指向的變數的值
*ptr = 12  				// i=12  更新指標指向的變數的值
fmt.Println(*ptr,i)		// 12 12
複製程式碼

上面這段程式碼,宣告瞭*int 型別的指標變數 ptr ,通過取址運算子&獲得指向整型變數 i 的地址。可以說,指標ptr指向變數i,或者說ptr指標儲存了變數i的地址。

指標宣告

通過上面一段話的解釋,相信大家對指標有了比較清晰的認識:指標指向一個變數的記憶體地址。要想使用指標,必須先宣告,格式如下:

var var_name *var_type
// var_name 指標名稱,var_type 指標所指向的變數的型別
複製程式碼
var i int = 10
str := "go"
var ip *int         // *int型別的指標
var pstr *string    // *string型別的指標
ip = &i
pstr = &str
fmt.Println(*ip,*pstr)     // 10 go
複製程式碼

注意*int型別的指標,說明該指標指向的一定是int型別的變數,*string型別也類似。

str := "go"
var ip *int
ip = &str  // 編譯不會通過
複製程式碼

*int 型別的指標,指向的變數若是string型別的,編譯器編譯的時候就會報錯:

cannot use &str (type *string) as type *int in assignment
複製程式碼

如何使用指標

文章寫到這裡,關於如何使用指標,其實上文已經列出來了,主要經過三個步驟:宣告賦值訪問指標指向的變數的值

x,y := 1,"go"
var px *int = &x    	// 1、宣告並初始化
var py = &y				// 2、省略指標型別,編譯器自動判斷
//px,py := &x,&y		// 3、使用 :=
fmt.Println(*px,*py) 	// 1 go   訪問
複製程式碼

關於空指標

一個指標已宣告而沒有賦值時,稱為空指標,為 nil 。任何型別的指標的零值都是 nil

var ip *int
fmt.Println(ip)							// nil
fmt.Printf("ip 的值為:%x", ip)			// ip 的值為:0
複製程式碼

如果ip != nil 為真,那麼p是指向某個有效變數。指標之間也是可以進行相等測試的,只有當它們指向同一個變數或全部是nil時才相等。

1、指向同一個變數 true
x,_ := 1,1
px,py := &x,&x
fmt.Println(px == py) 
 
2、指向不同變數 false
x,y := 1,1
px,py := &x,&y
fmt.Println(px == py)

3、兩個nil指標 true
var px *int
var py *int
fmt.Println(px == py)
複製程式碼

指標作為函式引數使用

指標包含的是一個變數的地址,如果將一個指標作為引數傳遞給函式,就可以通過指標來更新變數的值。

func a(p *int){
	*p++
}

i := 10
fmt.Println(i)      // 10
a(&i);
fmt.Println(i)		// 11
複製程式碼

不常用的new函式

給大家介紹下new函式,內建的new函式也是一種建立變數的方法,new(type)表示建立一個type型別的匿名變數,並初始化為type型別的零值,返回變數的地址,指標型別為*type

p := new(int)   	// p, *int 型別, 指向匿名的 int 變數
fmt.Println(*p) 	// 0
*p = 2          	// 設定 int 匿名變數的值為 2
fmt.Println(*p) 	// 2
複製程式碼

new函式建立變數和普通變數宣告語句方式建立變數沒有什麼區別,除了不需要宣告一個臨時變數的名字外。 下面的兩個函式有著相同的行為:建立變數,並返回變數地址

func newA() *int {
    return new(int)
}
func newB() *int {
    var i int
    return &i
}
複製程式碼

每次呼叫new函式都會返回新的變數的地址:

p := new(int)
q := new(int)
fmt.Println(p,q)   // 0xc000018060 0xc000018068
複製程式碼

new函式使用的比較少,不過覺得挺有意思的,就在這給大家分享下!實際程式設計,多的還是使用具體型別建立變數,畢竟更方便,是吧!


(全文完)

原創文章,若需轉載請註明出處!
歡迎掃碼關注公眾號「Golang來啦」或者移步 seekload.net ,檢視更多精彩文章。

公眾號「Golang來啦」給你準備了一份神祕學習大禮包,後臺回覆【電子書】領取!

公眾號二維碼

相關文章