Calling the pointer method on a structure on a map

There is a type of Company, which is a structure containing a Person's map, which are also all structures.

type Company struct { employees map[int]Person } type Person struct { [...] } 

After allocating some Person to the employee map, I try to call the pointer method for each of them.

 func (company *Company) Populate(names []string) { for i := 1; i <= 15; i++ { company.employees[i] = Person{names[i - 1], [...]} company.employees[i].Initialize() } } 

This terribly fails when the go compiler complains that I cannot call the pointer methods on company.employees [i] and I cannot use the address company.employees [i]. However, setting the Initialize method to a method without pointers and letting it return a copy of the person and assigning it to the map again using

 company.employees[i] = company.employees[i].Initialize() 

it works, which is not so different.

Not working with pointers, it really hurts me. The map is not immutable, and they are modified in any case, so calling the method of a pointer to an object on the map should not be a problem - at least in my head.

If someone could explain to me what I'm doing wrong here - or correct my thinking - I would be pleased.

+6
source share
2 answers

The problem is that to call the pointer method, you must specify the address employees[i] . According to Go specification:

The operand must be addressable, that is, either a variable, or a pointer, or indexing a fragment; or field selector of an address structural operand; or an indexing operation of an array of an address array. As an exception to the targeting requirement, x can also be a composite literal.

Card indexing operation is not addressed. This was decided, so map implementations did not have to guarantee that the addresses of the values ​​would not change. As more data is added to the map, it can move data for reasons of efficiency.

So how can you fix this? If you have map[int]*Person , you will not need to accept the address of the data on the map, since the value of the map is already an address.

One final Person.Initialize() advice, Person.Initialize() is not very idiomatic Go code. If you need to initialize a type, you usually use the NewPerson() function. The NewPerson() function returns an initialized structure or a Person pointer.

+11
source

For instance,

 package main import "fmt" type Person struct { Name string } func NewPerson(name string) *Person { return &Person{Name: name} } type Company struct { Employees map[int]*Person } func (c *Company) Populate(names []string) { c.Employees = make(map[int]*Person) for i := range names { c.Employees[i+1] = NewPerson(names[i]) } } func main() { c := Company{} c.Populate([]string{"Peter", "Paul"}) for k, v := range c.Employees { fmt.Println(k, *v) } } 

Conclusion:

 1 {Peter} 2 {Paul} 
0
source

All Articles