Slice statement
A slice can be regarded as a reference to an array (in fact, the underlying data structure of the slice is indeed an array). existGo
In , the size of each array is fixed and cannot be changed at will. Slicing can provide dynamic growth and shrinkage requirements for the array, but it does not store any data itself.
// Declaration of arrayvar a [5]int //Only specify the length, the element is initialized to the default value 0var a [5]int{1,2,3,4,5} // Slice statement// Method 1: Direct initializationvar s []int //Declare a nil slice with length and capacity of 0var s []int{1,2,3,4,5} // Create an array of length 5 at the same time// Method 2: Use make() function to create slicesvar s = make([]int, 0, 5) // Slice array: var variable name []Variable type = arr[low, high], low and high are the indexes of the array.// Remember the rules are: close left and open rightvar arr = [5]int{1,2,3,4,5} var slice []int = arr[1:4] // [2,3,4]
Length and capacity of slices
The length of the slice is the number of elements it contains. The capacity of a slice is the number from its first element to the end of its underlying array element. Slices
The length and capacity of can be expressed through expressionlen(s)
andcap(s)
Come and get it.
s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} (s, len(s), cap(s)) // output: [0 1 2 3 4 5 6 7 8 9] 10 10 s1 := s[0:5] (s1, len(s1), cap(s1)) // output: [0 1 2 3 4] 5 10 s2 := s[5:] (s2, len(s2), cap(s2)) // output: [5 6 7 8 9] 5 5
Changes in length and capacity after adding elements in slices
append function
Go
Provides built-inappend
Function, append new elements to the slice.
func append(s []T, vs ...T) []T
append
The return value of is a slice containing all elements of the original slice plus the newly added element.
s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} (s, len(s), cap(s)) sResult := append(s, 11) (sResult, len(sResult), cap(sResult)) // output: // [0 1 2 3 4 5 6 7 8 9] 10 10 // [0 1 2 3 4 5 6 7 8 9 11] 11 20
At this time, we can discover that when weappend
When elements enter the slice, the length and capacity of the original slice change, but why does their changes happen?
Let’s take a look at how the source code is implemented.
Learning the source code of slices
Go
The data structure of the slice can be in the source codesrc/runtime/
View in . The following source code is based ongo1.16.7
Version.
Sliced structure
As a reference to an array, slices have three attribute fields: pointer to the array, length and capacity.
type slice struct { // Pointer to the underlying array array // slice The current number of elements, that is, the number returned by len() len int // The capacity of slice, that is, the number returned when cap() cap int }
Slice expansion
slice
By callingappend
Functions are targetedslice
Append elements at the tail, if at this timeslice
ofcap
Value is less than the currentlen
Plusappend
The number of values passed in will be calledFunction, expand capacity.
We only release code analysis of basic expansion rules here. If you are interested in memory alignment, data copying, etc., you can view the corresponding source code yourself.
Basic expansion rules
func growslice(et *_type, old slice, cap int) slice { newcap := doublecap := newcap + newcap // If the new capacity is greater than twice the old capacity, apply directly according to the new capacity size if cap > doublecap { newcap = cap } else { // If the original length is less than 1024, the new capacity is twice the old capacity if < 1024 { newcap = doublecap } else { // Increase at 1/4 of the original capacity until the new capacity needs are met for 0 < newcap && newcap < cap { newcap += newcap / 4 } if newcap <= 0 { newcap = cap } } } }
From the source code, you can actually sort out several rules:
When the original slice length is less than 1024, the new slice length is directly addedappend
The number of elements and capacity will be directly*2
When the original slice length is greater than or equal to 1024, the new slice length is directly addedappend
The number of elements will increase1/4
Summarize
A slice is a structure that holds the capacity, length and pointers to an array (the address of the array).
From the source code, when a slice is expanded, it will growslice, which is a very expensive operation. In daily development, if we can clearly know the length or capacity of the slice, we need to declare it during initialization to avoid the expenses caused by frequent expansion of the slice.
This is the end of this article about explaining the difference between the length and capacity of slices in Go. For more related Go languages, please search for my previous articles or continue browsing the related articles below. I hope you can support me more in the future!