This article has participated in the third phase of the “High production” track at the Digger Creators Camp. For more details, check out the third phase of the Digger Project | Creators Camp to “write” personal impact.
Slice slices are more flexible than arrays because they can be easily expanded, passed, etc. For some basic use of slicing, see the previous article, Portal.
Here’s a closer look at Slice. Let’s take a look at some code to test your understanding of Slice.
The answer link
- What does the following program output?
package main
import (
"fmt"
)
func main(a) {
var array [20]int
var slice = array[10:11]
fmt.Println("lenth: ".len(slice))
fmt.Println("capacity: ".cap(slice))
fmt.Println(&slice[0] == &array[10])}Copy the code
Answer is:
lenth: 1
capacity: 10
true
Copy the code
Slice is created from array and shares storage space with array. Slice starts at array[5], length is 1, capacity is 5, address of slice[0] and array[5] are the same.
- What does the following program output?
package main
import (
"fmt"
)
func main(a) {
orderLen := 5
order := make([]uint16.2 * orderLen)
pollorder := order[:orderLen:orderLen]
lockorder := order[orderLen:][:orderLen:orderLen]
fmt.Println("len(pollorder) = ".len(pollorder))
fmt.Println("cap(pollorder) = ".cap(pollorder))
fmt.Println("len(lockorder) = ".len(lockorder))
fmt.Println("cap(lockorder) = ".cap(lockorder))
}
Copy the code
Answer is:
len(pollorder) = 5
cap(pollorder) = 5
len(lockorder) = 5
cap(lockorder) = 5
Copy the code
- order
[low:high:max]
Slice order. The new slice range is[low, high)
, the new slice volume is Max; - OrderLen of length 2;
- A pollOrder slice is the first half slice of an order;
- Lockorder is the second half of the order slice, that is, the original order divided into two segments;
- So pollOrder and LockerOrder are orderLen in length and capacity, which is 5.
Slice implementation Principle
The source code package SRC/Runtime /slice.go defines slice data structures as follows:
type slice struct {
array unsafe.Pointer
len int
cap int
}
Copy the code
- The array pointer points to the underlying array
- Len indicates the slice length
- Cap indicates the slice capacity
Make to create a slice
Make creates a slice by specifying both its length and its capacity. The underlying layer allocates an array, and the length of the array is the capacity.
Slice = make([]int,5,10): make([]int,5,10)
Array creation slice
When an array is used to create a slice, the slice shares a portion of memory with the original array. Slice := array[5:7];
The slicing starts with array[5] and ends with array[7] (excluding Array [7]). The length of the slicing is 2, and the contents after the array are used as the reserved memory of the slicing, that is, the capacity is 5.
Slice capacity
When append is used to append elements to a slice, an expansion occurs if the slice space is insufficient. The expansion realallocates a larger chunk of memory, copies the original slice to the new slice, and returns the new slice. Add data after expansion.
The expansion operation only applies to the capacity. After the expansion, the slice length remains the same. The capacity changes according to the following rules:
- If the size of the slice is sufficient, the new element is appented, slice.len++, and the original slice is returned
- If the size of the slice is insufficient, the slice is first expanded to obtain a new slice. The new elements are added to the new slice, slice. Len++, and the new slice is returned.
slice copy
When you use the copy() built-in function to copy two slices, the data of the source slice is copied one by one into the array pointed to by the destination slice. The number of copies is the minimum of the lengths of the two slices.
For example, when you copy a slice of length 10 to a slice of length 5, five elements will be copied. In other words, copy does not expand.
-
Slice := array[start:end] := array[start:end] := array[start:end]
-
Slice [start:end:cap], where cap is the capacity of the new slice, and the capacity cannot exceed the actual value of the original slice.
conclusion
- When creating slices, you can pre-allocate capacity based on actual requirements to avoid capacity expansion during the addition process, which improves performance
- When copying slices, determine the number of elements to be copied
- Be careful to use multiple slices for the same array to prevent read/write collisions
- Each slice points to an underlying array
- Each slice holds the length of the current slice and the available capacity of the underlying array
- When len() and cap() are used to calculate the length and capacity of slices, the time complexity is O(1) and there is no need to traverse slices
- When passing a slice through a function, the entire slice is not copied, because the slice itself is just a structure
- Using append() to append elements to slices can trigger expansion, which will generate new slices