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

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-17 09:55:28

问题


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 it in the slice, I then retrieve it as a pointer and want to change the name to "Peter", but the change does not work since it still prints "Steve". Why?

type Individual interface {
    GetName() *string
    SetName(name string)
}

type Person struct {
    name string
}

// Implement functions of the Individual interface
func (p Person) GetName() *string  {
    return &p.name
}

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


var individuals []Individual

func main() {
    person := Person{name: "Steve"}
    fmt.Println(person)

    individuals = append(individuals, person) // append Person to slice
    p1 := individuals[0]     // Retrieve the only Person from slice
    p1.SetName("Peter")      // Change name
    fmt.Println(p1)          // Should print "Peter", but prints "Steve"
    fmt.Println(person)      // Should print "Peter", but prints "Steve"
}

回答1:


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.




回答2:


Two things to fix this:

  • You need the methods attach via a "pointer" method, otherwise the name is only changed inside the method.
  • You need to use pointers for the actual Person variables, since they need to implement an interface
type Individual interface {
    GetName() *string
    SetName(name string)
}

type Person struct {
    name string
}

// Implement functions of the Individual interface
func (p Person) GetName() *string  {
    return &p.name
}

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


var individuals []Individual

func main() {
    person := &Person{name: "Steve"}
    fmt.Println(person)

    individuals = append(individuals, person) // append Person to slice
    p1 := individuals[0]     // Retrieve the only Person from slice
    p1.SetName("Peter")      // Change name
    fmt.Println(p1)          // Prints "Steve"
    fmt.Println(person)      // Prints "Steve"
}

Example on Go Playground.




回答3:


See https://play.golang.org/p/eg8oYDV6Xx p1 and p2 are already addresses, you don't need to their address (address of address), just print p1 and p2 - they'll be the same as you can see.



来源:https://stackoverflow.com/questions/43890706/my-object-is-not-updated-even-if-i-use-the-pointer-to-a-type-to-update-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!