對於一門語言,在函數傳參時,存在兩種方式,一種是值傳遞,一種是引用傳遞,那麼go語言是怎麼進行參數傳遞的
值傳遞是傳遞的變數的副本,引用傳遞指的是傳遞該變數的地址,在值傳遞過程中,函數對函數形參數的修改,不會導致實參的修改,而引用傳參,對形參的修改,會導致該實參的修改,這是過去我們在其它語言中的一些認知,那麼go語言會顛覆我們過去的認知,使用了一種新的方式.
package mainimport ( "fmt")func main() { a := 10 fmt.Println("實參的地址",&a) update(a) fmt.Println(a)}func update(b int) { b = 1 fmt.Println("形參的地址",&b)}// 運行結果實參的地址 0x10414020形參的地址 0x1041402410
由該demo,我們可以得出,在值傳遞時,形參是實參的一個copy
package mainimport ( "fmt")func main() { a := 10 p := &a fmt.Println("指標的地址",&p) fmt.Println("實參的地址",&a) update(p) fmt.Println(a)}func update(b *int) { *b = 1 fmt.Println("形參的指標地址",&b) fmt.Println("形參的地址",b)}// 運行結果指標的地址 0x1040c128實參的地址 0x10414020形參的指標地址 0x1040c138形參的地址 0x104140201
發現在指標傳遞時,實參和形參的指標地址不一值,但其指向地址是一樣的,由此可以得出,在指標傳遞時,go語言,傳遞的是指標的copy,是一種值傳遞的方式
再來看一個複雜的,結構體
package mainimport ( "fmt")type Person struct { Name string}func main() { p := Person{"zhang san"} fmt.Printf("實參的地址:%p\n", &p) update(p) fmt.Println(p)}func update(p Person) { p.Name = "li si" fmt.Printf("形參的地址:%p\n", &p)}// 輸出結果實參的地址:0x1040c128形參的地址:0x1040c138{zhang san}
指標傳遞
package mainimport ( "fmt")type Person struct { Name string}func main() { p := Person{"zhang san"} pr := &p fmt.Printf("實參的指標地址:%p\n", &pr) fmt.Printf("實參的地址:%p\n", &p) update(pr) fmt.Println(p)}func update(p *Person) { p.Name = "li si" fmt.Printf("形參的指標地址:%p\n", &p) fmt.Printf("形參的地址:%p\n", p)}// 運行結果實參的指標地址:0x1040c130實參的地址:0x1040c128形參的指標地址:0x1040c140形參的地址:0x1040c128{li si}
由demo3和demo4的對比,分析可以得到,在值傳遞時,傳遞的是值的實參的副本,指標傳遞時,傳遞的是指標的副本,其都指向實參的地址
通過以上實驗,可以得出,無論是值傳遞和指標傳遞,都傳遞的是對應的一個副本.在go語言中,只有一個值傳遞.
package mainimport ( "fmt")type Person struct { Name string}func main() { persons:=make(map[string]int) persons["張三"]=19 //mp:=&persons fmt.Printf("原始map的記憶體位址是:%p\n",&persons) update(persons) fmt.Println("map值被修改了,新值為:",persons)}func update(p map[string]int) { fmt.Printf("函數裡接收到map的記憶體位址是:%p\n",&p) p["張三"]=20}// 運行結果原始map的記憶體位址是:0x1040c128函數裡接收到map的記憶體位址是:0x1040c138map值被修改了,新值為: map[張三:20]
該demo運行結果和我們前面的推論結果不一致,在代碼中有一個特殊的make,因此我們有理由懷疑,make得到的結果是一個指標類型,這樣才符合我們前邊的推論.