Photograph by Sigmund on Unsplash

Unlike JavaScript, Go Passes an "Object Instance" to a Function

GoJavaScript

NB: Set aside any functional programming principles for the sake of this example.

How things work in JavaScript

When you pass an object into a function, the function receives the instance of that object, meaning that the function body can directly mutate that very same object. Put differently, JavaScript passes a reference to that object rather than a copy of its value.

const sample = {
  one: "Original value",
  two: "Original value"
};

console.log(sample); // Logs: {one: "Original value", two: "Original value"}
mutate(sample);
console.log(sample); // Logs: {one: "Original value", two: "New value"} --> Mutated

function mutate(s) {
  s.two = "New value";
}

How things work in Go

When you pass an object (or instance of a struct in Go parlance), the function receives a copy of that object, meaning that the function body cannot directly mutate that very same object. In other words, Go passes a copy of that object's value rather than a reference to it. (Run this example yourself here.)

package main

import (
  "fmt"
)

type sample struct {
  one string
  two string
}

fun main() {
  s := sample {
    one: "Original value",
    two: "Original value",
  }
  fmt.Printf("%+v", s) // Logs: {one:Original value two:Original value}
  mutate(s)
  fmt.Printf("%+v", s) // Logs: {one:Original value two:Original value} --> Not mutated
}

func mutate(s sample) {
  s.two = "New value"
}

How to make Go behave like JavaScript

It is possible to pass a reference to an object (i.e., struct) in Go that then allows for direct mutation of that same object, but it must be done explicitly. That is, you must pass a pointer (or reference) to the object that is passed into the function. (Run this example yourself here.)

package main

import (
  "fmt"
)

type sample struct {
  one string
  two string
}

func main() {
  s := sample {
    one: "Original value",
    two: "Original value",
  }
  fmt.Printf("%+v", s) // Logs: {one:Original value two:Original value}
  mutate(&s)
  fmt.Printf("%+v", s) // Logs: {one:Original value two:New value} --> Mutated
}

func mutate(s *sample) {
  s.two = "New value"
}