Junior
How do slices work in Go?
sobes.tech AI
Answer from AI
A slice is a lightweight wrapper over an array. It does not store data itself but references a base array.
Slice structure:
- Pointer to the base array: The address of the first element of the slice in memory.
- Length: The number of elements in the slice.
- Capacity: The number of elements in the underlying array available from the slice pointer.
// Example of declaring a slice
var s []int
s = append(s, 1, 2, 3) // Adding elements
// Internal representation of slice s (simplified)
// struct SliceHeader {
// Data uintptr // Pointer to the base array
// Len int // Length of the slice
// Cap int // Capacity of the slice
// }
- When creating a slice with
make([]T, length, capacity), a base array of the specified capacity is created, and the slice references it with the specified length. - When slicing an array or another slice (e.g.,
arr[low:high:max]), a new slice is created that references the same memory area of the base array but with different pointer, length, and capacity. - The
appendoperation may lead to reallocation. If the current capacity is insufficient to add new elements, Go creates a new, larger base array, copies the old array's elements into it, and updates the slice pointer to the new array. This is called reallocation. The growth algorithm for capacity during append is exponential (doubling up to a certain size, then slowing growth). - Slices are passed by value, but since they contain a pointer to the base array, changes to slice elements (via index) will be visible in all slices referencing the same base array.
- Changing the length of a slice via slicing does not affect the base array but may limit access to parts of the base array data.
Table: Comparison of Length and Capacity
| Characteristic | Length | Capacity |
|---|---|---|
| Definition | Actual number of elements in the slice | Maximum number of elements the slice can hold without reallocation |
| Access | Used to access elements (s[i]) |
Determines how many more elements can be added via append before reallocation |
| Retrieval | len(s) |
cap(s) |
// Example of working with capacity and length
s := make([]int, 0, 5) // Length 0, capacity 5
fmt.Println(len(s), cap(s)) // 0 5
s = append(s, 1, 2) // Adding 2 elements
fmt.Println(len(s), cap(s)) // 2 5
s = append(s, 3, 4, 5, 6) // Adding 4 more elements, reallocation needed
fmt.Println(len(s), cap(s)) // 6 10 (capacity increased)