0

I am new to Golang and am trying to append the contents of a slice of struct into another instance. The data gets appended but it is not visible outside the method. Below is the code.

package somepkg import ( "fmt" ) type SomeStruct struct { Name string Value float64 } type SomeStructs struct { StructInsts []SomeStruct } func (ss SomeStructs) AddAllStructs(otherstructs SomeStructs) { if ss.StructInsts == nil { ss.StructInsts = make([]SomeStruct, 0) } for _, structInst := range otherstructs.StructInsts { ss.StructInsts = append(ss.StructInsts, structInst) } fmt.Println("After append in method::: ", ss.StructInsts) } 

Then in the main package I initialize the structs and invoke the AddAllStructs method.

package main import ( "hello_world/somepkg" "fmt" ) func main() { var someStructs = somepkg.SomeStructs{ []somepkg.SomeStruct{ {Name: "a", Value: 1.0}, {Name: "b", Value: 2.0}, }, } var otherStructs = somepkg.SomeStructs{ []somepkg.SomeStruct{ {Name: "c", Value: 3.0}, {Name: "d", Value: 4.0}, }, } fmt.Println("original::: ", someStructs) fmt.Println("another::: ", otherStructs) someStructs.AddAllStructs(otherStructs) fmt.Println("After append in main::: ", someStructs) } 

The above program output is below:

original::: {[{a 1} {b 2}]} another::: {[{c 3} {d 4}]} After append in method::: [{a 1} {b 2} {c 3} {d 4}] After append in main::: {[{a 1} {b 2}]} 

I am trying to understand what I am missing here since the data is visible in the method. Appreciate any help on this.

-- Anoop

3 Answers 3

2

Use pointer receiver:

func (ss *SomeStructs) AddAllStructs(otherstructs SomeStructs) { if ss.StructInsts == nil { ss.StructInsts = make([]SomeStruct, 0) } for _, structInst := range otherstructs.StructInsts { ss.StructInsts = append(ss.StructInsts, structInst) } fmt.Println("After append in method::: ", ss.StructInsts) } 

If the method needs to mutate the receiver, the receiver must be a pointer

Sign up to request clarification or add additional context in comments.

Comments

0

You have to return the result of append:

package main import ( "fmt" ) func main() { // Wrong var x []int _ = append(x, 1) _ = append(x, 2) fmt.Println(x) // Prints [] // Write var y []int y = append(y, 1) y = append(y, 2) fmt.Println(y) // Prints [1 2] } 

2 Comments

I am doing that in the AddAllStructs method. The result of append is being assigned back to StructInsts and the appended value is being printed correctly in the method.
Yes but you are not returning it from AddAllStructs. Therefore when you send otherStructs you are sending a reference to one thing (in this case nil), however append creates a new piece of memory to make room for the new entry. When you don't return it, that reference is lost within the scope of the function. You have to return it from the function.
0

You can easily solve this problem by using pointer receiver instead of value receiver.

func (ss *SomeStructs) AddAllStructs(otherstructs SomeStructs) { if ss.StructInsts == nil { ss.StructInsts = make([]SomeStruct, 0) } for _, structInst := range otherstructs.StructInsts { ss.StructInsts = append(ss.StructInsts, structInst) } fmt.Println("After append in method::: ", ss.StructInsts) } 

Remember in go, if you see a slice internals, it is a struct containing pointer to a data structure.

So the slice in the main, doesn't know the capacity of newly appended slice and same slice has been printed.

Secondly , You don't have to return the result of the appended slice. here pointer receiver comes for rescue, as value receivers can't change the original value.

running code at go playground : https://play.golang.org/p/_vxx7Tp4dfN

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.