There is no cosmetic in the world that can make people more beautiful than happiness. – bretton
Internal implementation of slicing
A slice is a small object that abstracts the underlying array and provides related manipulation methods.
As you can see, the slice has three metadata: a pointer to the head of the underlying array, one for the length of the slice, and one for the size of the slice.
Create a slice
usemake
To create.
slice1 := make([]int) // nil
Slice2 := make([]int, 5) // {0, 0, 0, 0, 0
Slice3 := make([]int, 5, 10) // {0, 0, 0, 0} can increment to 10 elements
Copy the code
There doesn’t seem to be much difference between the slice2 and slice3 values here, but the container metadata determines whether or not to create a new underlying array when you use append, which is explained below.
A slice with less than its length will report an error during compilation
Literal creation
// Create a string slice
// Its length and capacity are both 5 elements
slice := []string{"Red", "Blue", "Green", "Yellow", "Pink"}
// Create an integer slice
// Its length and capacity are both 3 elements
slice := []int{10, 20, 30}
// Create a string slice
// Initialize the 100th element with an empty string
slice := []string{99: ""}
Copy the code
If at the time of creation[]
Write the value, for example[6]
, creating an array instead of a slice
Nil and empty slices
Since a slice is also a pointer, its null value is nil
var slice []int
// slice == nil
var slice1 []int{}
// slice1 ! = nil
len(slice1) == 0 // true
Copy the code
Create a slice using a slice
// Create an integer slice
// Its length and capacity are both 5 elements
slice := []int{10, 20, 30, 40, 50}
// Create a new slice
// Its length is 2 elements and its capacity is 4 elements
newSlice := slice[1:3]
Copy the code
After executing the slice action in Listing 4-25, we have two slicesShare the same underlying array, but you can see different parts of the underlying array through different slices (see Figure 4-12).
Add elements to the slice using append
// Create an integer slice
// Its length and capacity are both 5 elements
slice := []int{10, 20, 30, 40, 50}
// Create a new slice
// Its length is 2 elements and its capacity is 4 elements
newSlice := slice[1:3]
// Use the old capacity to allocate a new element
// Assign the new element a value of 60
newSlice = append(newSlice, 60)
Copy the code
The results are as follows
Note that the append function intelligently handles the capacity growth of the underlying array. When the size of the slice is less than 1000 elements, it always increases exponentially. Once the number of elements exceeds 1000, the capacity growth factor is set to 1.25, which is a 25% increase in capacity each time. This growth algorithm may change as the language evolves.
Look at the following code
slice := []int{1, 2, 3, 4}
NewSlice := append(slice, 5, 6);
NewSlice2 := append(newSlice, 6)
NewSlice2 [0] = 10 // Observe the values of the first two slices
fmt.Println(newSlice2[0]) // 10
fmt.Println(slice[0]) // 1
fmt.Println(newSlice[0]) // 10
Copy the code
You pass
When passing arrays between functions, the values of the arrays are copied. Too many arrays consume too much memory, so arrays are usually passed as func(arr *[]int) Pointers. However, slice is different from array in that it is only a pointer to array. Therefore, even if the underlying array is large, when the function is passed, only the slice (pointer) is copied, not the underlying array, so the transmission efficiency is very high.
Some of the code and some of the pictures in this article
Thanks to the author