Search code examples
gopass-by-reference

Cannot modify object by reference in golang


Why is it that I am not able to pass an object by reference in golang? I am 99% sure I am passing the object by reference to the function instead of copying the object. I am new to go and I always like making exercises like this before creating real code

Anyways my question is why does the last line printing Doggy? I was epecting for the last line to print name of dog after: changed name!

Code

package main

import "fmt"

// base type
type Animal struct {
    Name string
    Age  int
}

type Dog struct {
    Animal
    PropertyFoo1 int // some field specific to a dog
}

func modifyAnimalName(animal *Animal) {
    (*animal).Name = "changed name!"
}

func main() {

    // create a new dog
    dog := Dog{
        Animal: Animal{
            Name: "Doggy",
            Age:  5,
        },
    }

    var animal Animal = dog.Animal

    // before and after values when calling modifyAnimalName(&animal)
    fmt.Printf("name of dog before: %s \n", dog.Name)
    modifyAnimalName(&animal) // modify animal name
    // why does this prints Doggy?!
    fmt.Printf("name of dog after: %s \n", dog.Name)
}


console output:

name of dog before: Doggy 
name of dog after: Doggy

Edit

Sorry for asking this dumb question I just started learning go

@tkausl thanks. I just noticed thanks to your comment that this line was copying an entity object.

var animal Animal = dog.Animal

As a result I modified the code to:

    var animal *Animal = &dog.Animal

    fmt.Printf("name of dog before: %s \n", dog.Name)
    modifyAnimalName(animal)
    // now it prints a different name :)
    fmt.Printf("name of dog after: %s \n", dog.Name)

Solution

  • You are not passing by reference. Here's two solution to the problem.

    Solution 1: Using regular function

    package main
    
    import "fmt"
    
    // base type
    type Animal struct {
        Name string
        Age  int
    }
    
    type Dog struct {
        Animal
        PropertyFoo1 int // some field specific to a dog
    }
    
    func modifyAnimalName(animal *Animal) {
        animal.Name = "changed name!"
    }
    
    func main() {
        // create a new dog
        dog := Dog{
            Animal: Animal{
                Name: "Doggy",
                Age:  5,
            },
        }
    
        var animal *Animal = &dog.Animal
        fmt.Printf("name of dog before: %s \n", dog.Name)
        modifyAnimalName(animal) // modify animal name
        fmt.Printf("name of dog after: %s \n", dog.Name)
    }
    

    Solution 2: Using method

    package main
    
    import "fmt"
    
    type Animal struct {
        Name string
        Age  int
    }
    
    type Dog struct {
        Animal
        PropertyFoo1 int // some field specific to a dog
    }
    
    func (a *Animal) modifyAnimalName() {
        a.Name = "changed name!"
    }
    
    func main() {
        // create a new dog
        dog := Dog{
            Animal: Animal{
                Name: "Doggy",
                Age:  5,
            },
        }
        var animal *Animal = &dog.Animal
        fmt.Printf("name of dog before: %s \n", dog.Name)
        animal.modifyAnimalName()
        fmt.Printf("name of dog after: %s \n", dog.Name)
    }