“This is the 24th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

preface

The array mentioned before is not very flexible because it cannot expand its capacity. Slice is a contiguous memory space like array, which supports random access and can also flexibly change its capacity.

The data structure

type SliceHeader struct {
    Data unitptr
    Len  int
    Cap  int
}
Copy the code

Represents data, length and capacity respectively, where length represents how many elements are contained in the slice, and how many elements can be contained in the capacity code slice. When we continuously expand the slice so that the length of the slice is larger than its capacity, the slice will be expanded in accordance with some rules.

At initialization, the size and length of slices are equal by default, but you can specify the size and length of slices explicitly.

The underlying storage of slices

Section interception is a common operation. Here’s an example:

foo := make([]int.5);
foo[3] = 42
arr = foo[1:4]
arr[1] = 19
Copy the code

If you change the value of arr, you will change the value of foo. Therefore, we infer that slices still share an underlying data even if they are intercepted.

This interception is a bit of a “pass by reference” approach. In the previous article, we explained that arrays are both value copies, whether they are function arguments or copies of variables such as a=b.

func TestArray(t *testing.T) {
   a := []int{1.2.3}
   b := a
   c := b
   c[1] = 10
   t.Log(a)
}
Copy the code

Output: [1 10 3]

Is slicing a “reference” copy? No, it’s just that when you slice it, you copy the SliceHeader, so all three sliceHeaders are pointing to the same address. If the cost of copying is only two ints and one pointer, the cost of slice copying becomes extremely low, saving a lot of money compared to arrays.

Slice interception + splicing to delete the middle element

arr = append(arr[:x], arr[x+1:]...).Copy the code

No extra memory is required this way.