Sobes.tech
Junior

How can you slice in Go? What nuances and pitfalls might arise?

sobes.tech AI

Answer from AI

Slicing in Go is achieved using the syntax a[low:high], where low is the starting index (inclusive), and high is the ending index (exclusive). Other options include a[:high] (from the beginning to high), a[low:] (from low to the end), and a[:] (a copy of the entire slice).

Nuances and pitfalls:

  • Shared underlying array: Slicing creates a new slice that shares the underlying array with the original slice. Changes to elements in one slice will reflect in the other if they point to the same underlying array.
  • Changing capacity: The new slice has the same capacity as the original, reduced by low. This can lead to unexpected behavior when appending elements if the capacity is exceeded.
  • Out of bounds: low and high must be within [0, len(a)] and [0, cap(a)] respectively. Violating these will cause a runtime panic: slice bounds out of range.
  • Creating an independent copy: To create an independent copy, use the copy function.

Examples:

// Original slice
s := []int{1, 2, 3, 4, 5}

// Slice from index 1 to 3 (excluding 3)
s1 := s[1:3] // s1 will be {2, 3}

// Slice from start to index 3
s2 := s[:3] // s2 will be {1, 2, 3}

// Slice from index 2 to end
s3 := s[2:] // s3 will be {3, 4, 5}

// Copy of the entire slice
s4 := s[:] // s4 will be {1, 2, 3, 4, 5}

// Demonstrating shared underlying array
s1[0] = 100 // Change in s1
// Now s looks like {1, 100, 3, 4, 5}

// Creating an independent copy
s5 := make([]int, len(s))
copy(s5, s) // s5 is now {1, 100, 3, 4, 5}

// Changes in s5 won't affect s
s5[0] = 200
// s remains {1, 100, 3, 4, 5}
// s5 now {200, 100, 3, 4, 5}

Table illustrating the cap of sliced slices:

Original slice s len(s) cap(s) Slice Result len of slice cap of slice
{1, 2, 3, 4, 5} 5 5 s[1:3] {2, 3} 2 4
{1, 2, 3, 4, 5} 5 5 s[:3] {1, 2, 3} 3 5
{1, 2, 3, 4, 5} 5 5 s[2:] {3, 4, 5} 3 3
{1, 2, 3, 4, 5} 5 5 s[:] {1, 2, 3, 4, 5} 5 5

Understanding how the underlying array and capacity work is key to working efficiently with slices in Go and avoiding unexpected results.