Mistakes with append

· go's blog


Playground Link

package main

import "fmt"

func main() {
	// In go, a slice refers to an underlying array.
	// the slice itself contains a pointer to the underlying array,
	// a length, and a capacity.

	// So we have our slice literal.
	foo := []int{1, 2, 3}
	fmt.Println("Original slice", foo) // [1,2,3]

	// lets say we want to filter out the value at index 1
	bar := append(foo[:1], foo[2:]...)

	// but now foo is different???
	fmt.Println("Original slice", foo) // [1,3,3]
	fmt.Println("Filtered slice", bar) // [1,3]

	// this is because append is operating on foo's underlying array. append figured
	// we have enough room in this array to accomdate our now shorter array, and returns
	// a new slice with a shorter length over the same underlying array.

	// see, exact same addresses
	fmt.Println("foo", &foo[1])
	fmt.Println("bar", &bar[1])

	// so when we update the values
	bar[0] = 9
	bar[1] = 10

	// foo and bar are looking at the same underlying array, but with different lengths
	fmt.Println("Original slice after update", foo) // prints [9,10,3]
	fmt.Println("Filtered slice after update", bar) // prints [9,10]
	// we never modified the slice foo so its length is still 3.

	// we can avoid the issue we had with append
	// by introducing a new slice.
	foo = []int{1, 2, 3}
	bar = append(append([]int{}, foo[:1]...), foo[2:]...)

	fmt.Println("Solution foo", foo) // [1,2,3]
	fmt.Println("Solution bar", bar) // [1,3]

}