Creating a new slice by removing an element from a slice alters the original and others

Hi,

I am having issues with removing elements from a slice. Essentially what I am trying to achieve is taking some base slice of elements and creating multiple new slices each with a single index removed from the base slice. An example program that illustrates this would be the following:

package main

import (
	"fmt"
)

func main() {
	base := []int{1, 2, 3, 4, 5}
	removal1 := RemoveElement(base, 0)
	removal2 := RemoveElement(base, 1)

	fmt.Printf("%v\n", base)
	fmt.Printf("%v\n", removal1)
	fmt.Printf("%v\n", removal2)
}

func RemoveElement(slice []int, index int) []int {
	return append(slice[:index], slice[index+1:]...)
}

What I would expect to see is:

  • [1, 2, 3, 4, 5]
  • [2, 3, 4, 5]
  • [1, 3, 4, 5]

What I do see instead is:

  • [2, 4, 5, 5, 5]
  • [2, 4, 5, 5]
  • [2, 4, 5, 5]

I don’t know whether I am doing something wrong, but I cannot figure out what the cause is or how to fix it. Any assistance or ideas would be appreciated.

EDIT

Somehow right after posting I had the idea of using a new variable like this:

func RemoveElement(slice []int, index int) []int {
	newSlice := []int{}
	newSlice = append(newSlice, slice[:index]...)
	newSlice = append(newSlice, slice[index+1:]...)
	return newSlice
}

This seems to fix the issue so I assume that my original code somehow alters the original though I would like to try and understand why as to me it should all be by reference.

Hi!
You are using and overwriting the slice.
Replace the RemoveElement function with the following func to debug:

func RemoveElement(slice []int, index int) []int {
	a := slice[:index]
	fmt.Printf("a: %p\n", a)
	b := slice[index+1:]
	fmt.Printf("b: %p\n", b)
	c := append(a, b...)
	fmt.Printf("c: %p\n", c)
	return c
}

In this case, the address of “a” and “c” are the same.
You are “appending” to the begging of the pointer.

You can simply use or copy the code of the std slices.Delete func

Because your base slice doesn’t trigger scaling, you’re actually modifying the same underlying array. append decides whether to return the same underlying array based on whether the capacity is exceeded.