GO語言也有指針,本質上和C/C++沒有差別,但是在用法上有很多差別,GO語言中的指針是弱化版的C/C++指針。
先來看一段簡單的代碼
func main() {
a := 1
b := &a
fmt.Println(reflect.TypeOf(b),b,*b)
}
執行結果如下
*int 0xc04204e080 1
由此可見:
- 這個b的類型就是int類型的指針,用*int表示
- b指向了a,b的值就是a的地址,也就是說a的地址就是0xc04204e080
- *b就是解引用指針,得到的是a的值,也就是1
基本的用法看起來和C++好像沒有太大的變化,但是還是有幾點是需要注意的。
指針的零值
C/C++中指針可以爲NULL,那麼在GO語言中,空指針就是nil了,這也是我們說的指針的零值(不賦值時候的值)。
GO語言中的指針不能拿來運算
GO語言中的指針是簡單的,弱化版的C/C++指針,就是因爲GO語言規定指針不可以進行運算,而C/C++中的指針可以進行++/--操作,也可以進行+1,+2這樣的運算操作,GO語言簡單就是簡單在它規定了這樣的操作是不合法的,編譯器會自動報錯。
值傳遞配合指針實現引用傳遞
在函數傳參的時候,GO語言只有值傳遞一種方式,沒有引用傳遞。
來看下面的代碼
func print(a int){
fmt.Println(a)
}
func main() {
a := 1
print(a)
}
這就是典型的值傳遞,才調用print函數的時候,會拷貝一份變量a,作爲形式參數傳給print函數,調用完print函數之後,這個臨時的拷貝的變量就被銷燬了。這中間有一次拷貝操作,如果這個變量不是int,而是一個自定義類型,且這個類型的大小非常大。那我們如果拷貝了這個變量,肯定就會消耗一定的空間。
這個時候我們就可以使用指針來搞定,同時這也保證了,這次值傳遞傳遞的是變量的地址,而不是整個變量,起到了引用傳遞的效果。
func print(pa *int){
*pa = 2 //將pa指向的地址的值改爲了2
fmt.Println(*pa)
}
func main() {
a := 1
fmt.Println(a) //執行print函數之前a是1
print(&a)
fmt.Println(a) //執行print函數之後a是2
}
來看下輸出結果
1
2
2
a的值在調用完print函數以後發生了變化,是因爲print函數體內通過指針改變了原來的值,這個C語言的實現的引用傳遞方式類似。