了解指標接收器和複製實例
在 Go 中,可以使用值接收器或指標接收器來定義方法。當類型 T 的所有方法都具有 T 本身的接收者類型時,複製該類型的實例是安全的,因為呼叫其任何方法都必然會進行複製。
但是,當類型有帶有指標接收器的方法時。在這種情況下,應避免複製該類型的實例,因為它可能違反內部不變量。
複製指標的問題
讓我們考慮一個範例來說明問題。假設我們有一個有兩個欄位的類型 Wrapper:值 v 和指標 p。我們打算在 v 和 p 的指向值中儲存相同的數字。為了確保這一點,我們提供了一個帶有指標接收器的 Set 方法:
<code class="go">type Wrapper struct { v int p *int } func (w *Wrapper) Set(v int) { w.v = v *w.p = v }</code>
如果我們有一個 Wrapper 實例並呼叫 Set 方法,它將修改 p 的指向值。但是,如果我們建立實例的副本,則副本將與原始實例共用相同的指標值 p。這意味著對任一實例的任何後續方法呼叫都會影響兩個副本。
範例:
<code class="go">a := Wrapper{v: 0, p: new(int)} b := a fmt.Printf("a.v=%d, a.p=%d; b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p) a.Set(1) fmt.Printf("a.v=%d, a.p=%d; b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)</code>
輸出:
a.v=0, a.p=0; b.v=0, b.p=0 a.v=1, a.p=1; b.v=0, b.p=1
In本例中,呼叫a.Set(1) 後,b 的值變成無效,因為b.v 不等於*b.p。這是因為 a 和 b 中的指標 p 都指向相同的基礎值。
為了避免此類問題,建議在使用帶有指標接收器的方法時使用指標值。或者,如果該類型只能具有值接收器,則無論方法呼叫如何,複製該類型的實例都是安全的。
以上是## 為什麼我不能在 Go 中只複製帶有指標接收器的類型實例?的詳細內容。更多資訊請關注PHP中文網其他相關文章!