Analysis of slice in golang

Summary:

What can you get after reading this article

1. Able to understand the structure of slices in detail

2. Be able to understand the relationship and difference between slices and arrays

3. Be able to understand the expansion rules and logic of slices.

Let's get started:

1. Initialize a slice first.

a := make([]int, 1, 2)

As we know, Slice has three params!

The first parameter is to specify the type of slice, and the second parameter is to specify how many data len to store. The third parameter is the specified space cap (how much data memory is allocated, or how much data can be stored in the allocated memory at most)

After making the above code, the system will allocate a contiguous memory for the a variable to hold 2 int elements, the default value is 0, and only 1 can be used. Because the position of the second parameter len of make is filled with 1, only a[0] can be used. If a[1] is used directly, an error will be reported directly out of bounds.

Use append to add a value to the len of the slice, so that the second position can be filled. At this time, the len of a becomes 2, and there is no problem in using a[1] directly.

a = append(a, 2)

Temporary summary: A slice is actually a structure composed of three parts. As shown in the figure below, the structure includes the address of an array pointed to, how many elements are stored in len, and how many elements can be stored in cap from the pointed address to the end of the memory (this is a bit convoluted, let’s talk about it in detail below ) click ).

2. Through the comparison of an array, understand the difference between slices and arrays

arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

This is a regular array, not a slice! The number of arrays cannot be changed, this is an array.

arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

slice1 := arr[3:5]

fmt.Println(slice1)

// 输出的值是 [4 5]

If a slice slice1 is defined on the basis of an array , at this time, the len of slice1 is 2, the cap is 7, and the len is 2. It is understandable, but why the cap is 7 is beyond comprehension.

Look at the figure below, 1-10 is a continuous memory of the array, slice [3:5], it does not generate new memory, but points to the third position of the memory 1-10 as the 0th data of the slice , a total of 2 were cut, but the definition of cap is how many quantities can be stored in a continuous memory from the pointed position to the end, so it is 7.

 

Note: If you add a piece of data to slice1, you cannot modify the original array. It will copy the value and create a new array with len=3 and cap=7. This will not destroy the original value of the array.

arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

slice1 := arr[3:5]

slice1 = append(slice1, 11)

Arrays are also encapsulated behind slices as support, so you should be able to understand the relationship between arrays and slices.

3. What happens when the slice is appended until the current continuous memory is full

As shown in the following code, make initializes a slice slice1, len=2, and cap is also equal to 2, which means that the initialization fills up the memory. At this time, another append element comes in. At this time, capacity expansion will start. The meaning of capacity expansion is that the old memory will be abandoned, and a memory with a cap of 4 will be re-applied. append a new value, len becomes 3.

slice1 := make([]int, 2, 2)

slice1 = append(slice1, 3)

4. Slicing expansion rules

The expansion rules of slices can be found in the source code. If you are interested, you can read the source code runtime/slice.go file.

 Briefly talk about the expansion rules of slices: the cap in the source code is the required quantity, the oldcap is the original quantity, and the newcap is the final quantity after calculation.

From the logic of the source code:

If the required quantity is greater than twice the old cap, then directly return the required quantity as the new cap quantity.

otherwise:

        If the number of elements is less than 1024, it will be doubled and returned directly

        If it is greater than 1024, add a quarter of the cap space.

Guess you like

Origin blog.csdn.net/weixin_38256311/article/details/122994307