我剛剛玩Exercise 51 in the Tour of Go。解釋權利要求Scale
方法在接收到Vertex
而不是指向Vertex
的指針時不起作用。爲什麼帶有指針接收器的方法在接收到值時仍然工作?
然而,當我在main
改變聲明v := &Vertex{3, 4}
到v := Vertex{3, 4}
輸出唯一的變化是缺少&
標記指針。
那麼爲什麼Scale
更改它接收的變量,即使該變量不是指針?
我剛剛玩Exercise 51 in the Tour of Go。解釋權利要求Scale
方法在接收到Vertex
而不是指向Vertex
的指針時不起作用。爲什麼帶有指針接收器的方法在接收到值時仍然工作?
然而,當我在main
改變聲明v := &Vertex{3, 4}
到v := Vertex{3, 4}
輸出唯一的變化是缺少&
標記指針。
那麼爲什麼Scale
更改它接收的變量,即使該變量不是指針?
它沒有「接收」一個值。 Go是強類型的,因此如果指定了T的指針,則指向T(*T
)的指針是唯一可以作爲這種類型位置的值的選項。
「魔術師」是在有效地「重寫」在一定conditions你的代碼編譯:
一個方法調用
x.m()
是有效的,如果(類型)的方法集x
包含m
和參數列表可以分配給參數列表m
。如果x
尋址和& X的方法集包含m
,x.m()
是(&x).m()
簡寫:
相關:Method sets
的旅遊建議不同的是沒有實際改變v := &Vertex{3, 4}
到v:= Vertex{3, 4}
,而是改變兩個方法的定義,以便它們處理值而不是指針。因此,例如,對於Scale
,func (v *Vertex) Scale(f float64) {...
變爲func (v Vertex) Scale(f float64) {...
(注意(v *Vertex)
,指針值變爲(v Vertex)
,非指針值)。在這兩種情況下,您都應該將v
的聲明保留爲v := &Vertex{3, 4}
。
您會注意到,在第一種情況下,當方法採用指針時,輸出爲&{15 20} 25
。但是,當方法取值而不是指針時,輸出爲&{3 4} 5
。
在這兩種情況下,v
都是指向Vertex
對象的指針。在第一種情況下,指針被傳遞給方法,並且所有事情都按預期工作 - 對Vertex
對象所做的任何修改都將設置爲原始值,因此這些更改在方法返回後仍然存在。在第二種情況下,儘管v
仍然是一個指針,但Go編譯器足夠智能,可以將v.Scale(5)
轉換爲(*v).Scale(5)
,其中v
已取消引用,並將結果值傳遞給Scale
。
所以,雖然在我的情況下'v'不是一個指針。 「規模」可以簡單地把它看作是一個嗎? – sjakobi
不,'Scale' **不能**將非指針作爲指針。答案中的規範解釋了爲什麼'Scale'會將'&v'作爲接收者,而不是**'v'。 – zzzz
好的。但是** I **可以將指針方法應用於值,就像它們本身就是指針一樣。謝謝你解釋這個! – sjakobi