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

usemakeTo 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