My object is not updated even if I use the pointer to a type to update it

后端 未结 3 1560
我在风中等你
我在风中等你 2020-11-29 11:38

I store some Individual objects in a slice. Before appending it to the slice I print the name of the Individual object.

After I have stored

3条回答
  •  旧巷少年郎
    2020-11-29 12:28

    Whenever a method wants to modify the receiver, it must be a pointer to the value; the method must have a pointer receiver.

    If a method has a non-pointer receiver, a copy will be made and passed when that method is called. From that point, no matter what you do with the receiver, you can only modify the copy, and not the original.

    So in your example:

    func (p Person) SetName(newName string)  {
        name := p.GetName();
        *name = newName
    }
    

    When SetName() is called, a copy is made of the Person. Inside SetName() you obtain the address of the name field of the copy, which you modify. (Actually, a copy of the copy, more on this later...)

    Solution: use a pointer receiver:

    func (p *Person) SetName(newName string)  {
        name := p.GetName();
        *name = newName
    }
    

    From this point on, only *Person implements Individual, so use a pointer when appending:

    individuals = append(individuals, &person)
    

    It's tricky, because after this it sill won't work. Why is that?

    It is because the Person.GetName() still has a non-pointer receiver:

    func (p Person) GetName() *string {
        return &p.name
    }
    

    So when GetName() is called from SetName(), a copy will be made again, and GetName() will return the address of the name field of the copy, and SetName() will only modify the copy created for calling GetName().

    So to make all work, you also have to use pointer receiver for GetName():

    func (p *Person) GetName() *string {
        return &p.name
    }
    

    And now it's working, output (try it on the Go Playground):

    {Steve}
    &{Peter}
    {Peter}
    

    But know that the easiest and recommended way is simply:

    func (p *Person) SetName(newName string) {
        p.name = newName
    }
    

    That's all it takes.

提交回复
热议问题