2 回答

TA貢獻(xiàn)1812條經(jīng)驗(yàn) 獲得超5個(gè)贊
將接收者定義為值
格式:
func (r T) Xxx() {}
可以通過值或指針調(diào)用。
當(dāng)用指針調(diào)用時(shí),值會(huì)自動(dòng)傳遞,(它實(shí)際上是用來*
獲取調(diào)用者的值,并傳遞它)。
將接收器定義為指針
格式:
func (r *T) Xxx() {}
原則上,應(yīng)該只用指針調(diào)用,但這不是必需的。
因?yàn)楫?dāng)調(diào)用值而不是指針時(shí),編譯器會(huì)在可能的情況下處理它:
如果該值是可尋址的,(對(duì)于 go 中的大多數(shù)數(shù)據(jù)類型都是如此)。
然后編譯器將獲取地址(通過&
),并自動(dòng)傳遞它。
這使得可以直接調(diào)用具有值的指針方法,(我猜這在 go 中很常見,它使程序員的生活更輕松)。如果該值不可尋址,(這種情況很少見,但存在)。
然后需要顯式傳遞地址,否則編譯時(shí)會(huì)出錯(cuò)。
egmap
的元素不可尋址。
尖端
如果合適,在定義方法時(shí)首選指針調(diào)用者。
原因:它可以修改調(diào)用者。
對(duì)于復(fù)雜的調(diào)用者來說,它更輕量級(jí)。
傳遞給方法的內(nèi)容取決于方法簽名,而不是您如何調(diào)用它(這與參數(shù)類似)。
當(dāng)將調(diào)用者聲明為指針時(shí)
(r *T)
,它傳遞指針。當(dāng)將調(diào)用者聲明為 value 時(shí)
(r T)
,它會(huì)傳遞原始調(diào)用者的副本。T
本身不能是指針。
代碼
并且,這是我在學(xué)習(xí)此功能時(shí)編寫的代碼。
它調(diào)用的2個(gè)函數(shù)main()
分別測試2個(gè)特性。
方法_learn.go:
// method - test
package main
import (
"fmt"
"math"
)
type Vertex struct {
x float64
y float64
}
// abs, with pointer caller,
func (v *Vertex) AbsPointer() float64 {
return math.Sqrt(v.x*v.x + v.y*v.y)
}
// scale, with pointer caller,
func (v *Vertex) ScalePointer(f float64) *Vertex {
v.x = v.x * f
v.y = v.y * f
return v
}
// abs, with value caller,
func (v Vertex) AbsValue() float64 {
return math.Sqrt(v.x*v.x + v.y*v.y)
}
// test - method with pointer caller,
func pointerCallerLearn() {
vt := Vertex{3, 4}
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n", vt, vt.AbsPointer(), "pointer", "value") // call pointer method, with value,
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n\n", vt, (&vt).AbsPointer(), "pointer", "pointer") // call pointer method, with pointer,
// scala, change original caller,
fmt.Printf("%v scale by 10 is: %v (Call %s method, with %s)\n", vt, vt.ScalePointer(10), "pointer", "value") // call pointer method, with value,
fmt.Printf("%v scale by 10 is: %v (Call %s method, with %s)\n", vt, (&vt).ScalePointer(10), "pointer", "pointer") // call pointer method, with pointer,
}
// test - method with value caller,
func valueCallerLearn() {
vt := Vertex{3, 4}
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n", vt, (&vt).AbsValue(), "value", "pointer") // call value method, with pointer,
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n", vt, vt.AbsValue(), "value", "value") // call value method, with value,
}
func main() {
// pointerCallerLearn()
valueCallerLearn()
}
只需修改main(),然后通過 運(yùn)行g(shù)o run method_test.go,然后檢查輸出以查看其工作原理。

TA貢獻(xiàn)1806條經(jīng)驗(yàn) 獲得超8個(gè)贊
它們之間的最大區(qū)別是價(jià)值接收者被復(fù)制*。所以如果你想改變你的接收器,你必須使用指針。觀察:
package main
import (
"fmt"
)
type Person struct {
Age int
}
func (p Person) GrowUp1() {
p.Age++
}
func (p *Person) GrowUp2() {
p.Age++
}
func main() {
p := Person{Age: 20}
fmt.Println(p)
p.GrowUp1()
fmt.Println(p)
p.GrowUp2()
fmt.Println(p)
}
// {20}
// {20}
// {21}
* 當(dāng)然,指針也會(huì)被復(fù)制。但由于它們是指針,指針的副本仍然指向同一個(gè)對(duì)象。
- 2 回答
- 0 關(guān)注
- 163 瀏覽
添加回答
舉報(bào)