Golang 中的指標 - Pointer

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

 

 

Go 的原生資料類型可以分為基本類型和進階類型,基本類型主要包含 string, bool, int 及 float 系列,進階類型包含 struct,array/slice,map,chan, func 。

 

相比 Java,Python,Javascript 等參考型別的語言,Golang 擁有類似C語言的指標這個相對古老的特性。但不同於 C 語言,Golang 的指標是單獨的類型,而不是 C 語言中的 int 類型,而且也不能對指標做整數運算。從這一點看,Golang 的指標基本就是一種引用。

 

那麼 Golang 為什麼需要指標?這種指標又能有什麼獨特的用途呢?

 

在學習參考型別語言的時候,總是要先搞清楚,當給一個函數/方法傳參的時候,傳進去的是值還是引用。實際上,在大部分引用型語言裡,參數為基本類型時,傳進去的大都是值,也就是另外複製了一份參數到當前的函數調用棧。參數為進階類型時,傳進去的基本都是引用。這個主要是因為虛擬機器的記憶體管理導致的。

 

記憶體管理中的記憶體地區一般包括 heap 和 stack, stack 主要用來儲存當前調用棧用到的簡單類型資料:string,boolean,int,float 等。這些類型的記憶體佔用小,容易回收,基本上它們的值和指標佔用的空間差不多,因此可以直接複製,GC也比較容易做針對性的最佳化。 複雜的進階類型佔用的記憶體往往相對較大,儲存在 heap 中,GC 回收頻率相對較低,代價也較大,因此傳引用/指標可以避免進行成本較高的複製操作,並且節省記憶體,提高程式運行效率。

 

因此,在下列情況可以考慮使用指標:1,需要改變參數的值;2,避免複製操作;3,節省記憶體;

 

而在 Golang 中,具體到進階類型 struct,slice,map,也各有不同。實際上,只有 struct 的使用有點複雜,slice,map,chan 都可以直接使用,不用考慮是值還是指標。

 

 

struct:

 

對於函數(function),由函數的參數類型指定,傳入的參數的類型不對會報錯,例如:

 

func passValue(s struct){} func passPointer(s *struct){}

 

對於方法(method),接收者(receiver)可以是指標,也可以是值,Golang 會在傳遞參數前自動適配以符合參數的類型。也就是:如果方法的參數是值,那麼按照傳值的方式 ,方法內部對struct的改動無法作用在外部的變數上,例如:

 

package main import "fmt" type MyPoint struct {    X int    Y int} func printFuncValue(p MyPoint){    p.X = 1    p.Y = 1    fmt.Printf(" -> %v", p)} func printFuncPointer(pp *MyPoint){    pp.X = 1 // 實際上應該寫做 (*pp).X,Golang 給了文法糖,減少了麻煩,但是也導致了 * 的不一致    pp.Y = 1    fmt.Printf(" -> %v", pp)} func (p MyPoint) printMethodValue(){    p.X += 1    p.Y += 1    fmt.Printf(" -> %v", p)} // 建議使用指標作為方法(method:printMethodPointer)的接收者(receiver:*MyPoint),一是可以修改接收者的值,二是可以避免大對象的複製func (pp *MyPoint) printMethodPointer(){    pp.X += 1    pp.Y += 1    fmt.Printf(" -> %v", pp)} func main(){    p := MyPoint{0, 0}    pp := &MyPoint{0, 0}     fmt.Printf("\n value to func(value): %v", p)    printFuncValue(p)    fmt.Printf(" --> %v", p)    // Output: value to func(value): {0 0} -> {1 1} --> {0 0}     //printFuncValue(pp) // cannot use pp (type *MyPoint) as type MyPoint in argument to printFuncValue     //printFuncPointer(p) // cannot use p (type MyPoint) as type *MyPoint in argument to printFuncPointer     fmt.Printf("\n pointer to func(pointer): %v", pp)    printFuncPointer(pp)    fmt.Printf(" --> %v", pp)    // Output: pointer to func(pointer): &{0 0} -> &{1 1} --> &{1 1}     fmt.Printf("\n value to method(value): %v", p)    p.printMethodValue()    fmt.Printf(" --> %v", p)    // Output: value to method(value): {0 0} -> {1 1} --> {0 0}     fmt.Printf("\n value to method(pointer): %v", p)    p.printMethodPointer()    fmt.Printf(" --> %v", p)    // Output: value to method(pointer): {0 0} -> &{1 1} --> {1 1}     fmt.Printf("\n pointer to method(value): %v", pp)    pp.printMethodValue()    fmt.Printf(" --> %v", pp)    // Output: pointer to method(value): &{1 1} -> {2 2} --> &{1 1}     fmt.Printf("\n pointer to method(pointer): %v", pp)    pp.printMethodPointer()    fmt.Printf(" --> %v", pp)    // Output: pointer to method(pointer): &{1 1} -> &{2 2} --> &{2 2}}

 

slice :

 

slice 實際上相當於對其依附的 array 的引用,它不儲存資料,只是對 array 進行描述。因此,修改 slice 中的元素,改變會體現在 array 上,當然也會體現在該 array 的所有 slice 上。

可以使用 make([]int) 來建立並初始化 map 。

 

 

map :

 

使用 make(map[string]string) 返回的本身是個引用,可以直接用來操作:

 

map["name"]="Jason";

 

而如果使用 map 的指標,反而會產生錯誤:

*map["name"]="Jason"  //  invalid indirect of m["title"] (type string)(*map)["name"]="Jason"  // invalid indirect of m (type map[string]string)

 

 

chan :

 

make(chan int) 返回的是可以直接使用的 channel 。

 

 

func :

 

在 Golang 中,func 可以作為一種值被返回,因此也可以使用類似 Python 的 decorator 的方式來加工函數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.