There is the type Company, which is a struct, containing a map of Person’s, which are also all structs.
type Company struct {
employees map[int]Person
}
type Person struct {
[...]
}
After allocating some Person’s to the employees-map, I’m trying to call a pointer method on each of these.
func (company *Company) Populate(names []string) {
for i := 1; i <= 15; i++ {
company.employees[i] = Person{names[i - 1], [...]}
company.employees[i].Initialize()
}
}
This miserably fails, with the go-Compiler complaining that I can’t call pointer methods on company.employees[i], as well as I can’t take the address of company.employees[i].
However, setting the Initialize-method to a non-pointer method and letting it return the copy of the person, and allocating it to the map again by using
company.employees[i] = company.employees[i].Initialize()
works, which is not that different.
Not having worked with pointers ever this bugs me quite much. Map’s aren’t immutable, and they get modified either way, so calling a pointer method on an entity in a map shouldn’t be a problem – atleast in my head.
If anyone could explain to me what I’m doing wrong here – or correct my thinking – I’d be pleased.
The problem here is that in order to call a pointer method, the address of
employees[i]needs to be taken. According to the Go specification:A map indexing operation is not addressable. This was decided so that map implementations would not need to guarantee that the addresses of values would not change. As more data is added to the map, it may relocate data for efficiency reasons.
So, how can you fix it? If you have a
map[int]*Person, you will not need to take the address of the data in the map since the map value is already an address.One last bit of advice,
Person.Initialize()is not very idiomatic Go code. If you need to initialize a type, you normally use aNewPerson()function. TheNewPerson()function would return an initialized Person struct or pointer.