當附加到Go 結構中的切片屬性
嘗試將值附加到Go 結構中的切片屬性時,您可能會遇到意外行為如果未遵循特定的呼叫順序。本文探討了此問題背後的原因並提供了解決方案。
在提供的程式碼範例中,在不同的結構類型中定義了三個方法來示範該問題。 Test1 和 Test2 按預期工作,因為它們的 run() 方法直接對切片屬性進行操作。然而,在 Test3 中,combo() 方法是使用值接收器而不是指標接收器從 run() 呼叫的。
為什麼需要指標接收器
在Go 中,所有值都是按值傳遞,這表示在呼叫函數或方法時會建立傳遞值的副本。在 Test3 的情況下,呼叫combo() 時會建立 Test3 值的副本,並且對該副本中的 slice 屬性的修改不會反映在原始 Test3 結構中。
透過使用指標接收器,如func(c *Test3)combo(),直接修改原先的Test3結構體,消除了copy-local的問題
解
解決方案是將combo()方法的接收者類型變更為指標接收者。這確保原始 Test3 結構體被該方法修改。
更新的程式碼
package main import ( "fmt" ) type Test1 struct { all []int } func (c Test1) run() []int { for i := 0; i < 2; i++ { c.all = append(c.all, i) } return c.all } var gloabl_all []int type Test2 struct {} func (c Test2) run() []int { c.combo() return gloabl_all } func (c Test2) combo() { for i := 0; i < 2; i++ { gloabl_all = append(gloabl_all, i) } } type Test3 struct { all []int } func (c Test3) run() []int { c.combo() return c.all } func (c *Test3) combo() { for i := 0; i < 2; i++ { c.all = append(c.all, i) fmt.Println("Test3 step", i + 1, c.all) } } func main() { test1 := &Test1{} fmt.Println("Test1 final:", test1.run()) test2 := &Test2{} fmt.Println("Test2 final:", test2.run()) test3 := &Test3{} fmt.Println("Test3 final:", test3.run()) }
輸出
Test1 final: [0 1] Test2 final: [0 1] Test3 step 1 [0] Test3 step 2 [0 1] Test3 final: [0 1]
以上是為什麼我需要一個指標接收器來附加到 Go 結構中的切片?的詳細內容。更多資訊請關注PHP中文網其他相關文章!