4

I have the following struct that has a function that can update its fields:

type Dog struct {
    name string
    age  int
}

func (dog *Dog) growOld() {    
    dog.name = "old dog"
    dog.age++
}

The above works fine on its own. However, when the struct belongs to another object and said object tells the struct to update its fields, the changes seem to occur but do not get applied:

package main

import (
    "fmt"
)

type Owner struct {
    dog Dog
}

func newOwner(dog Dog) Owner {
    var owner Owner
    owner.dog = dog

    return owner
}

func (owner Owner) tellDogToGrowOld() {
    owner.dog.growOld()
}

func main() {
    var dog Dog
    dog.name = "dog"

    owner := newOwner(dog)
    owner.tellDogToGrowOld()       

    fmt.Println(dog) // dog's name is still `dog` and age is 0.
}

I assume I have to use pointers somehow but can't quite figure out how.

3
  • 3
    tellDogToGrowOld needs to be defined on a pointer just like you did with growOld. Or, alternatively, Owner's dog field needs to be pointer to Dog. Commented Mar 19, 2019 at 8:50
  • @mkopriva Hey, it worked! Please add this as an answer so I can accept it. Thanks! Commented Mar 19, 2019 at 8:51
  • @mkopriva I went with the Owner's dog field should be a pointer to Dog approach because it's the closest to "pass-by-reference" in other languages. Commented Mar 19, 2019 at 8:56

2 Answers 2

10

The type of a method's receiver should be a pointer type if you want that method to modify the receiver's state.

That is, the same way as you've declared the growOld method, the tellDogToGrowOld method should also have a pointer reciever:

func (owner *Owner) tellDogToGrowOld() {
    owner.dog.growOld()
}

Alternatively, you could make the field that you want to modify to be a pointer, e.g.:

type Owner struct {
    dog *Dog
}

func newOwner(dog *Dog) Owner {
    var owner Owner
    owner.dog = dog

    return owner
}

func (owner Owner) tellDogToGrowOld() {
    owner.dog.growOld()
}
Sign up to request clarification or add additional context in comments.

Comments

3

Set the field in the Owner to be a *Dog not a Dog

type Owner struct {
    dog *Dog
}

func newOwner(dog *Dog) Owner {
    var owner Owner
    owner.dog = dog

    return owner
}

when calling from main use &dog

var dog Dog
    dog.name = "dog"

    owner := newOwner(&dog)

https://play.golang.org/p/LpFqW09dOs4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.