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:
lowandhighmust 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
copyfunction.
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.