在 Go 中,帶有指標接收器的方法會保留其操作的變數的原始值在。然而,當一個方法需要一個指標參數並傳遞一個非指標值時,似乎存在明顯的矛盾。
考慮Go 之旅中練習51 的以下程式碼片段:
func (v *Vertex) Scale(f float64) { v.X *= f v.Y *= f } func main() { v := &Vertex{3, 4} v.Scale(2) fmt.Println(v) // Output: &{6 8} }
根據解釋,Scale方法不應該修改v,因為它接收的是指向Vertex(*Vertex)的指針而不是Vertex
但是,當我們將main 中的v := &Vertex{3, 4} 行改為 v := Vertex{3, 4} 時,輸出從 &{6 8} 改為 {6 8 (注意缺少 &)。這表示 v 已被修改,即使它作為非指標值傳遞。
關鍵在於 Go 的強型別性質與編譯器最佳化。即使 Scale 方法需要一個指標接收器,它仍然可以接受非指標值,因為 Go 會隱含地將它們轉換為指標。
具體來說,編譯器重寫以下程式碼:
v := Vertex{3, 4} v.Scale(2)
to:
(&v).Scale(2)
這表示該方法實際上是用指向v 的指針呼叫的,這允許它修改原始的
以下特定於Go的規則解釋了此行為:
如果 x(的類型)的方法集包含 m 並且參數列表可以,則方法調用 x.m() 是有效的被分配給m的參數列表。如果 x 是可尋址的,且 &x 的方法集包含 m,則 x.m() 是 (&x).m() 的簡寫。
綜上所述,具有指標接收器的方法仍然可以修改非指標變量,因為編譯器會自動轉換它們指向指標以保持方法類型安全。
以上是為什麼帶有指標接收器的 Go 方法會修改非指標參數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!