I am going through the tour of Go and wanted to know the following:
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Drop its last two values
s = s[:len(s)-2]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
Result:
len=6 cap=6 [2 3 5 7 11 13]
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
Why does the capacity of the slice stay the same when you drop the last 2 items but changes when you drop the first 2?
https://play.golang.org/p/ZNKwOYKDqOi
In Go, the length of a slice tells you how many elements it contains. It can be obtained using the len() function. The capacity is the size of the slice's underlying array and can be obtained with the cap() function.
Removing an Element from a Slice Items need to be removed from a slice by slicing them out. To remove an element, you must slice out the items before that element, slice out the items after that element, then append these two new slices together without the element that you wanted to remove.
Remove first element of slice (shift, pop(0))
operator, Go calculates the size of the array for us. We create a slice from the vals array. The resulting slice contains elements starting from index 5 up to index 7; the upper bound is non-inclusive.
Go slices are implemented as a struct:
src/runtime/slice.go
:
type slice struct {
array unsafe.Pointer
len int
cap int
}
Revise your printSlice
function to show the pointer to the underlying array:
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Drop its last two values
s = s[:len(s)-2]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
var ptr *int
if cap(s) >= 1 {
ptr = &s[:cap(s)][0]
}
fmt.Printf("ptr=%p len=%d cap=%d %v\n", ptr, len(s), cap(s), s)
}
Playground: https://play.golang.org/p/pk3cpE_LsUV
Output:
ptr=0x450000 len=6 cap=6 [2 3 5 7 11 13]
ptr=0x450000 len=4 cap=6 [2 3 5 7]
ptr=0x450008 len=2 cap=4 [5 7]
See how your slicing operations adjust the pointer, the length, and the capacity. A slice is simply a view of or window into the underlying array.
References:
The Go Blog: Go Slices: usage and internals
The Go Programming Language Specification:
Slice types
Slice expressions
A slice has a buffer under the covers. The capacity is the size of that buffer. Removing items from the end does not alter the buffer size.
You are creating a new slice from an existing slice but starting the index of the new slice at 2. The new slice still points to the same underlying buffer (but offset by 2). The buffer size (and capacity) for this new slice is thus 2 less.
Capacity makes sense when you see how append works. Append tries to reuse the same underlying buffer - but if the capacity is filled, then a reallocation and copy is performed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With