Appending to Slice Properties in Go Structs
When attempting to append values to a slice property within a Go struct, you may encounter unexpected behavior if a specific call order is not followed. This article explores the reasons behind this issue and provides a solution.
In the code example provided, three methods are defined within different struct types to demonstrate the issue. Test1 and Test2 work as expected because their run() methods directly operate on the slice property. However, in Test3, the combo() method is called from run() using a value receiver instead of a pointer receiver.
Why a Pointer Receiver Is Required
In Go, all values are passed by value, meaning a copy of the passed value is created when calling a function or method. In the case of Test3, a copy of the Test3 value is made when combo() is called, and modifications to the slice property in this copy are not reflected in the original Test3 struct.
By using a pointer receiver, such as func (c *Test3) combo(), the original Test3 struct is directly modified, eliminating the issue of copy-local changes.
Solution
The solution is to change the receiver type of the combo() method to a pointer receiver. This ensures that the original Test3 struct is being modified by the method.
Updated Code
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()) }
Output
Test1 final: [0 1] Test2 final: [0 1] Test3 step 1 [0] Test3 step 2 [0 1] Test3 final: [0 1]
The above is the detailed content of Why Do I Need a Pointer Receiver to Append to a Slice in a Go Struct?. For more information, please follow other related articles on the PHP Chinese website!