0

Compare these two examples

(from: https://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/)

package main

import "fmt"

type Person struct {
    firstName string
    lastName  string
}

func changeName(p Person) {
    p.firstName = "Bob"
}

func main() {
    person := Person {
        firstName: "Alice",
        lastName: "Dow",
    }

    changeName(person)

    fmt.Println(person)
}

The code above returns {Alice Dow} so the struct is not changed.

Now in this example

package main

import "fmt"

func main() {
    slice := []string{"a", "b", "c"}

    fmt.Println(slice)
    updateSlice(slice)
    fmt.Println(slice)
}

func updateSlice(slice []string) []string {
    slice[0] = "x"
    return slice
}

the output is

[a b c]
[x b c]

so the slice was changed by the func updateSlice.

Would someone explain the difference?

mr_yoda
  • 19

1 Answers1

1

A slice is a reference to an underlying array. So, when you pass a slice to a function, you are essentially passing a reference to the underlying array.

In the first code snippet, when you call changeName(person), Go will create a copy of the person struct and pass it to the changeName function.

func main() {
    person := Person {
        firstName: "Alice",
        lastName: "Dow",
    }

    changeName(person) //Go will pass a copy of the person struct

    fmt.Println(person)
}

A slice in Go is just a reference to an underlying array; a slice is not an array. In the second example, updateSlice(slice) also passes by value. It creates a copy of slice. However, in this case, Go is creating a copy of a reference to an array. That means, that the "copy of slice" and "slice" are both pointing to the same underlying array.

func main() {
    slice := []string{"a", "b", "c"}

    fmt.Println(slice)
    //Go is still passing by value here, but the value passed is a reference
    // i.e. the copied value still points to the same underlying array
    updateSlice(slice)
    fmt.Println(slice)
}

Just in case you are trying to compare how a slice function in other languages like Javascript or Ruby work to a Slice in Go, don't (mentioning this because I did that when I was learning Go).

To add a little more clarification, when you do slice[0] = "x", you are not modifying the slice; you are modifying the underlying array that slice is referencing.

Ankit
  • 6,772
  • 11
  • 48
  • 84
  • Interesting, so if I am reading this right, there is close to zero sense in passing a reference to a slice to func like this ```updateSlice(&slice)``` ? – mr_yoda Sep 15 '21 at 01:01
  • I am not 100% sure, but I think if you pass `&slice`, it might be slightly memory efficient since Go does not have to create a copy of that reference. – Ankit Sep 15 '21 at 01:14