Reputation: 113
I am having some thought issues with the following code
package main
import (
"fmt"
)
type Company struct {
Name string
Workers []worker
}
type worker struct {
Name string
Other []int
}
func (cmp *Company) NewWorker(name string) worker {
wrk := worker{Name: name}
cmp.Workers = append(cmp.Workers, wrk)
return wrk
}
func main() {
cmp := Company{}
cmp.Name = "Acme"
wrk := cmp.NewWorker("Bugs")
for i := 1; i <= 10; i++ {
wrk.Other = append(wrk.Other, i)
}
fmt.Println(wrk)
fmt.Println(cmp)
}
https://play.golang.org/p/Bja7u148mg
As you can see the code is not returning the worker I am creating but a copy of it. How can I get it to return the actual worker? I have tried some variations of * and & on the different workers but I end up with either:
invalid indirect of worker literal (type worker)
or:
cannot use wrk (type worker) as type *worker in return argument
Any ideas on how to do this?
Upvotes: 11
Views: 51956
Reputation: 10158
func (cmp *Company) NewWorker(name string) *worker {
wrk := worker{Name: name}
cmp.Workers = append(cmp.Workers, wrk)
return &wrk
}
&
always means "take the address of" (except for the binary bitwise operator version). *
, however, changes meaning depending on the context. The expression *Type
means "pointer to Type". The express *Pointer
means "the object that Pointer points to". This is why you get an invalid indirect of worker literal
if you try to use the expression *wrk
, because you're saying "give me the object that wrk
points to", but wrk
isn't a pointer.
As such, you need *worker
as your return type (returning a pointer to a worker), and you return &wrk
, the address of the structure you're returning.
Another alternative is to use the built in new()
to create a pointer in the first place:
func (cmp *Company) NewWorker(name string) *worker {
wrk := new(worker)
wrk.Name = name
cmp.Workers = append(cmp.Workers, *wrk)
return wrk // wrk is a pointer here
}
All that said, there's little reason to return a pointer to your worker structure here. The structure itself only has two fields, both of which are already reference types (strings are essentially just immutable slices), so the entire structure is only 5 machine words long (so 20 or 40 bytes, depending on whether you're on 32bit or 64bit). You're not modifying the struct after return, and the version you store in the Company struct is also a copy (Company holds a slice of workers, not a slice of pointers to workers).
Upvotes: 29