http://www.tizgrape.com/?p=100
Go語言中的指針語法和C++一脈相承,都是用*
作為符號,雖然語法上接近,但是實際差異不小。
Go使用var
定義變量:
var v6 *int // int* v6; (but no pointer arithmetic) x = *p (*int)(nil) // function pointer
Go雖然有指針,但是沒有指針算數,不能對其進行加減。但可以把指針值賦給另一個指針,因此Go的指針更像是C++的引用,卻又沒有C++中引用初始化后不能重新賦值的限制。
Go使用nil
來表示無效指針,C++使用NULL(0)
或nullptr
(C++11)來表示空指針。
當指向一個struct結構體時,Go的指針使用.
而不是->
來引用結構體的成員:
type myStruct struct { i int }
var v9 myStruct // v9 has structure type
var p9 *myStruct // p9 is a pointer to a structure
f(v9.i, p9.i)
指針在Go中是“安全”的,指針無法指向任意的內存區域,緩沖區溢出的問題不會發生。但注意,解引用一個空指針同樣能導致Go程序崩潰。
指針的使用是和內存的分配緊密相關的。C&C++需要手動管理內存,然而Go使用垃圾收集器自動管理內存,這樣就減少很多使用指針上的操心。首先我們再也不需要顯示釋放內存,懸掛指針(dangling pointer,指向已釋放的內存)以及多次釋放同一個指針指向內存的問題就不會發生。我們甚至不用擔心內存是在棧上分配的還是堆上分配的。C++中的各種智能指針std::unique_ptr
,std::shared_ptr
, std::weak_ptr
, std::auto_ptr
也用不上了。一切都由Go的運行時系統幫助處理。
在Go中,取一個變量的地址是安全的,不會產生懸掛指針。如果在程序中取了一個變量的地址,編譯器會自動在棧上分配這個變量,下面的三個函數是等價的:
type S { I int }
func f1() *S {
return new(S)
}
func f2() *S {
var s S
return &s
}
func f3() *S {
// More idiomatic: use composite literal syntax.
return &S{}
}
反之,在C++函數中,返回一個函數局部變量的指針是一個低級錯誤。
// C++ S* f2() { S s; return &s; // INVALID -- contents can be overwritten at any time }