Go Slices: Difference between revisions
Line 11: | Line 11: | ||
A slice contains a [[#Pointer|pointer to the underlying array]], a [[#Length|length]] and a [[#Capacity|capacity]]. More details available in the [[#Structure|structure]] section. A slice, once initialized, is always associated with the underlying array that holds its elements. The slice shares storage with its array, and other slices of the same array. A distinct slice that shares the underlying array with an original slice can be created by slicing the original slice with a [[Go_Slice_Expressions#Overview|slice expression]]. | A slice contains a [[#Pointer|pointer to the underlying array]], a [[#Length|length]] and a [[#Capacity|capacity]]. More details available in the [[#Structure|structure]] section. A slice, once initialized, is always associated with the underlying array that holds its elements. The slice shares storage with its array, and other slices of the same array. A distinct slice that shares the underlying array with an original slice can be created by slicing the original slice with a [[Go_Slice_Expressions#Overview|slice expression]]. | ||
Once the slice is initialized and the association with the underlying array is established, the association never changes, and the underlying array never changes. Specifically, it cannot be grown and shrunk. However, a slice can be grown beyond the limits imposed by the original array, by allocating a new array under the covers, creating a new slice, copying elements across and using the second slice as the first slice. For more details, see <code>append()</code> below. | |||
Slices [[Go_Slices#Slices_and_Pass-by-Value|are passed by value]], like an other Go variable, but when that happens, the slice argument of a function and the internal variable copy of the slice still share the underlying array. | Slices [[Go_Slices#Slices_and_Pass-by-Value|are passed by value]], like an other Go variable, but when that happens, the slice argument of a function and the internal variable copy of the slice still share the underlying array. |
Revision as of 01:29, 19 August 2024
External
Internal
Overview
A slice is a descriptor, or a header, for a contiguous segment of an underlying array, stored separately from the slice variable. The slice provides access to a numbered sequence of elements from that array. A slice type denotes the set of all slices of arrays of its element type.
A slice contains a pointer to the underlying array, a length and a capacity. More details available in the structure section. A slice, once initialized, is always associated with the underlying array that holds its elements. The slice shares storage with its array, and other slices of the same array. A distinct slice that shares the underlying array with an original slice can be created by slicing the original slice with a slice expression.
Once the slice is initialized and the association with the underlying array is established, the association never changes, and the underlying array never changes. Specifically, it cannot be grown and shrunk. However, a slice can be grown beyond the limits imposed by the original array, by allocating a new array under the covers, creating a new slice, copying elements across and using the second slice as the first slice. For more details, see append()
below.
Slices are passed by value, like an other Go variable, but when that happens, the slice argument of a function and the internal variable copy of the slice still share the underlying array.
The Go documentation used to refer to slices as reference types, but not anymore. The "reference type" terminology was removed from Go documentation.
Structure
Under the covers, a slice is a structure that contains:
- a pointer to the first element of the slice, as stored in the underlying array.
- an integer length of the slice.
- an integer capacity
These elements are referred to as the contents, or the fields, or the elements, or the components of the slice.
Pointer
Length
Capacity
Slices and Pass-by-Value
Go uses pass-by-value, so when a slice argument is passed to a function, the internal fields are copied across on the function stack, including the pointer to the underlying array. Therefore, the underlying array data structure is intrinsically shared, even in case of pass-by-value. Both the original slice header and the copy of the header passed to the function describe the same array. If the function changes the underlying array via its copy of the slice, the modified elements can be seen outside the function through the original slice variable.
However, if the function modifies the elements of the slice, like the length, or the pointer to the array element, those changes naturally do not propagate outside of the function. Only the changes to the underlying array do.