0

Could someone help explain the Golang internals of why this code is mutating the original array a?

func main() {
    a := []int{1,2,3,4}
    b := a
    b = append(b[0:1], b[2:]...)
    fmt.Println(b)
    fmt.Println(a)
}

Output:

[1 3 4]
[1 3 4 4]

I thought b := a would be passing by value. Thanks in advance.

jub0bs
  • 60,866
  • 25
  • 183
  • 186
Say.My.Name.
  • 511
  • 5
  • 19
  • 1
    You can use a [three-index slice expression](https://golang.org/doc/go1.2#three_index) to "detach" slice `b` from slice `a`: https://play.golang.org/p/olHOm9A60xE – jub0bs Aug 28 '21 at 17:56

2 Answers2

5

That's how slices work. A slice is just a pointer(+size+capacity), the actual data is stored in the array.

When you copy a slice, the underlying array is not copied. Then you end up with two slices pointing to the same array. Mutating the values of one slice will become visible via the other slice.

See Go Slices: usage and internals for more details.

If you want to leave the original slice untouched, first make a deep copy. For example like this

    b := append([]int{}, a...)  // deep copy

(Live demo)

rustyx
  • 80,671
  • 25
  • 200
  • 267
1

Slices are basically wrapper over arrays. Slices doesn't have their own data they just hold the reference to the arrays. In your given code you are assigning a to b now they both are indicating the same array. And so when you are mutating the slice b the slice a is also being mutated.

You can use copy method to copy elements from one array to another.

// copy returns the count of total copied elements
count := copy(b /*destination*/ , a /*source*/)

But make sure to allocate an array with the same length of source array. Example is given below:

func main() {
    a := []int{1,2,3,4}
    b := make([]int, len(a))

    _ = copy(b, a)

    a[0] = 2

    fmt.Println(b)
    fmt.Println(a)
}
Dipto Mondal
  • 624
  • 1
  • 4
  • 14