Learn what
What is slicing?
How do I create slices?
How to get slice length and capacity?
The relationship between slices and arrays?
Operation slice specific elements?
How are slice elements appended and removed?
Is the slice a reference type or a value type?
How do I copy slices?
How do I create multidimensional slices?
What is the slice string?
concept
Before learning slicing, please put the previous article< Built in collection array >Find out.
Slicing is similar to a variable length array, unlike an array whose length is fixed. However, the bottom layer of the slice still uses an array. The slice only saves the reference to the array to help manage the array and achieve variable effects.
statement
Format: var slice name [] data type
The difference between array declaration and array declaration is whether the length is specified. If there is no length, it is slice.
var nums []int
Note: the slice is uninitialized. The default is nil and the length is 0. If you empty the slice, you can assign nil, for example: num = nil.
initialization
1. make function
Use the make function to initialize the slice. The capacity (which will be explained later) parameter can be omitted. After omission, the length and capacity are equal. The format is as follows:
Slice name := make([]Data type, length, capacity)
Example:
// Length 2, capacity 5 nums := make([]int, 2, 5)
The following figure is a schematic diagram of the sample code. Let's get a deeper understanding of slicing.
The blue area is the slice structure, which contains the array pointer (ptr), slice length (len), and slice capacity (cap).
ptr: array pointer, memory address of the array, pointing to the specific index of the array.
Len: the length of the slice, which can be obtained using the len (Num s) function, indicating the length used from the index position corresponding to the pointer.
Cap: the capacity of the slice, which can be obtained using the cap (Num s) function and represents the length of the reference array.
The yellow area is the array referenced by the bottom layer of the slice, and the length of the array is the capacity of the slice.
2. Initialize specific values
nums := []int{1, 2, 3}
A slice with a length of 3 is initialized, and the capacity is also 3.
Operation specific elements
The specific operation of the elements in the slice is the same as that of the array. If the slice length is exceeded when getting the element, the compiler will report an error even if the capacity is not exceeded.
nums := []int{1, 2, 3} // Set the element of index 1 to 4 nums[1] = 4 fmt.Println(nums[1]) // output 4
Get subset
After defining a slice or array, you can get a part of it, that is, a subset.
Format: slice or array [start index: end index]
Gets the subset from the start index to the end index, including the start index but not the end index. If it is an array, the type will be converted to slice type after obtaining a subset.
// section nums := []int{1, 2, 3, 4, 5} // Get slice subset nums1 := nums[2:4] // []int{3, 4} // array arr := [5]int{1, 2, 3, 4, 5} // nums2 is the slice type nums2 := arr[2:4] // []int{3, 4}
Omit index
"Start index" and "end index" can be omitted.
The start index is omitted, indicating that the subset starts from index 0 to the end index.
If the end index is omitted, it means that the subset is indexed from the beginning to the end.
Both are omitted. If it is a slice, the two are the same. If it is an array, it will be converted to the slice type.
nums := []int{1, 2, 3, 4, 5} // Start index omit nums1 := nums[:3] // []int{1, 2, 3} // End index ellipsis nums2 := nums[2:] // []int{3, 4, 5} // nums3 is the same as nums // Equivalent to: nums3: = nums nums3 := nums[:]
If nums in the code is an array, nums [:] will convert the array into slices. Let's take a look at the schematic diagram of the above code, which will deepen our understanding.
It can be seen from the figure that all slices point to the same array, which also shows that the slice is a reference type and will not be copied during transmission.
Append and remove elements
Append elements to the slice. Use the append function, which can only be appended to the end of the slice.
// collection/slice-append.go nums := []int{1, 2, 3} nums = append(nums, 2) nums = append(nums, 4, 5) fmt.Println(nums) // output [1 2 3 2 4 5]
If you want to append to the beginning of the slice, there is no native function. Use the implementation of append redirection. This method is actually merging two slices.
// collection/slice-append-front.go nums := []int{1, 2, 3} // ... three points indicate that the slice element expansion is passed to the function nums = append([]int{4}, nums...) fmt.Println(nums) // output [4 1 2 3]
How to remove an element? Use the slice subset and the append function to change the direction.
// collection/slice-append-remove.go nums := []int{1, 2, 3, 4, 5} // Remove element value 3 with index 2 nums = append(nums[:2], nums[3:]...) fmt.Println(nums) // output [1 2 4 5]
Slice copy
1. copy function
It is learned from the above that slice is a reference type, so it cannot be directly assigned to a new variable like array, and a copy will be generated. Next, use the copy function to copy the slice.
// collection/slice-copy-1.go // Copy nums to numsCopy nums := []int{1, 2, 3} numsCopy := make([]int, 3) copy(numsCopy, nums) // numsCopy is modified and will not affect nums numsCopy[0] = 2 fmt.Println("nums:", nums) fmt.Println("numsCopy:", numsCopy) // output nums: [1 2 3] numsCopy: [2 2 3]
The length of numcopy can be less than or greater than the length of nums. If it is less than, the front part of nums will be copied, and if it is greater than, the rear part of numcopy will be retained.
// collection/slice-copy-2.go // numsCopy length is less than nums nums := []int{1, 2, 3} numsCopy := make([]int, 2) // The first two elements 1 and 2 are copied copy(numsCopy, nums) fmt.Println("numsCopy(less than):", numsCopy) // numsCopy length is greater than nums numsCopy = []int{4, 5, 6, 7} // 4,5,6 will be overwritten and 7 will be retained copy(numsCopy, nums) fmt.Println("numsCopy(greater than):", numsCopy) // output numsCopy(less than): [1 2] numsCopy(greater than): [1 2 3 7]
2. "Len gt h > capacity" triggers copying
When using the append function to add elements to the slice, if the added length is greater than the capacity of the slice, the underlying array space of the slice will be reopened to a larger place than the original, and the original array value will be copied.
Notes:
The two positions of "new array" in the figure are the moments when the slice length is greater than the capacity. These two moments will automatically open up a new array without any association with the original array, but only copy the value.
When creating a "new array" in the figure, the size of the capacity is twice that of the original, but this is not invariable, and the algorithm will be different in different cases. If you want to understand clearly, I recommend an article< Slice of deep decryption Go language>.
Multidimensional slice
This is similar to the multidimensional array. The only difference is that the slice does not specify the length. For example:
// Declare 2D slice var mult [][]int // Initialize 2D slice students := [][]int{ {2, 2, 0}, {2, 2, 2}, {2, 1, 2}, {2, 2, 2}, }
Note: if you want to create three-dimensional slice and four-dimensional slice, just compare it with multi-dimensional array.
Slice string
What is this? It is a string. You can use the subset usage above to get a part of the string.
str := "I'm laomiao." fmt.Println(str[4:7]) // output lao
summary
This article focuses on "slicing", which is often used in practical development, so we must master it clearly. The article does not specify how to traverse slicing, because it is the same as the use of array. If you don't understand, please read the previous article.