Everything in Go is passed by value. And a copy is made of the passed value.
Test3.combo()
has value (non-pointer) receiver:
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)
}
}
This means when Test3.combo()
is called from Test3.run()
like c.combo()
, a copy is made of c
(which is of type Test3
). The combo()
method operates on a copy. It properly appends 2 numbers to Test3.all
, but when this method returns, the copy is discarded.
So when Test3.run()
returns c.all
, it returns an empty (nil
) slice, because the slice to which Test3.combo()
appended, was a field of a copy, and which has been discarded.
Solution: simply use a pointer receiver:
func (c *Test3) combo() {
for i := 0; i < 2; i++ {
c.all = append(c.all, i)
fmt.Println("Test3 step", i + 1, c.all)
}
}
Output (try it on the Go Playground):
Test1 final: [0 1]
Test2 final: [0 1]
Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: [0 1]
Note the star *
in the receiver: func (c *Test3) combo()
. By adding it, you make the receiver a pointer, and so when combo()
is called, it only receives a pointer to a value of type Test3
, and it will modify the pointed value, the value that Test3.run()
has, so when combo()
returns, the changes are not lost.