当前位置:网站首页>go slice

go slice

2022-04-23 20:39:00 baboon_ chen

go slice characteristic

1、slice It's not an array or an array pointer . It refers to... Through internal pointers and related properties ⽤ Array ⽚ paragraph , To achieve change ⻓⽅ case .

  • lead ⽤ type . but ⾃⾝ It's a structure , Value copy ⻉ Pass on .
  • attribute len surface ⽰ can ⽤ Element quantity , Read and write operations cannot exceed this limit .
  • attribute cap surface ⽰ most ⼤ Expand capacity , Cannot exceed array limit .
  • If slice == nil, that len、cap The result is equal to 0.


runtime.h

struct Slice
{
                            // must not move anything
    byte*    array;      // actual data
    uintgo   len;        // number of elements
    uintgo   cap;        // allocated number of elements
};

 Insert picture description here

len = high - low

cap = max - low


Example :

func test1() {
    
	data := [...]int {
    0,1,2,3,4,5,6,7,8,9}
	s1 := data[:6:8]		//  Omit low
	s2 := data[5:]			//  Omit high、max
	s3 := data[:3]			//  Omit low、max
	s4 := data[:]			//  Omit low、high、max, It is equivalent to referring to the whole array 

	fmt.Printf("the value of s1: %v, cap: %d, len: %d\n", s1, cap(s1), len(s1))
	fmt.Printf("the value of s2: %v, cap: %d, len: %d\n", s2, cap(s2), len(s2))
	fmt.Printf("the value of s3: %v, cap: %d, len: %d\n", s3, cap(s3), len(s3))
	fmt.Printf("the value of s4: %v, cap: %d, len: %d\n", s4, cap(s4), len(s4))
	
	
	s1[1] = 100
	fmt.Printf("the value of s1: %v, cap: %d, len: %d\n", s1, cap(s1), len(s1))
	fmt.Printf("the value of s4: %v, cap: %d, len: %d\n", s4, cap(s4), len(s4))
	
}

Output :

the value of s1: [0 1 2 3 4 5], cap: 8, len: 6
the value of s2: [5 6 7 8 9], cap: 5, len: 5
the value of s3: [0 1 2], cap: 10, len: 3
the value of s4: [0 1 2 3 4 5 6 7 8 9], cap: 10, len: 10
the value of s1: [0 100 2 3 4 5], cap: 8, len: 6
the value of s4: [0 100 2 3 4 5 6 7 8 9], cap: 10, len: 10

2、 Can be created directly slice object ,⾃ Dynamically allocate the underlying array .

Example :

func test2() {
    
	s1 := []int {
    0, 1, 2, 3, 8:100}		//  Construct through initialization expression , Can make ⽤ Reference no. . The difference from constructing an array is that there is no specified length .
	s2 := make([]int, 6, 8)				//  send ⽤ make  establish , Appoint  len  and  cap  value .
	s3 := make([]int, 6)				//  Omit  cap, amount to  cap = len.

	fmt.Printf("the value of s1: %v, cap: %d, len: %d\n", s1, cap(s1), len(s1))
	fmt.Printf("the value of s2: %v, cap: %d, len: %d\n", s2, cap(s2), len(s2))
	fmt.Printf("the value of s3: %v, cap: %d, len: %d\n", s3, cap(s3), len(s3))
	
	p := &s1[2]		//  You can directly manipulate the underlying array through the pointer  
	*p += 100
	fmt.Printf("the value of s1: %v, cap: %d, len: %d\n", s1, cap(s1), len(s1))

}

Output :

the value of s1: [0 1 2 3 0 0 0 0 100], cap: 9, len: 9
the value of s2: [0 0 0 0 0 0], cap: 8, len: 6
the value of s3: [0 0 0 0 0 0], cap: 6, len: 6
the value of s1: [0 1 102 3 0 0 0 0 100], cap: 9, len: 9

send ⽤ make Dynamically create slice, Avoid the array must ⽤ Constant doing ⻓ Degree ⿇ Bother .

3、 Slice of slice .

⾄ On [][]T, Means that the element type is []T.

data := [][]int{
    
    []int{
    1, 2, 3},
    []int{
    100, 200},
    []int{
    11, 22, 33, 44},
}

4、reslice

So-called reslice, It is based on the existing slice Create a new slice object , In order to be in cap Adjust attributes within the allowed range .

Example :

s := []int{
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := s[2:5]        // [2 3 4]
s2 := s1[2:6:7]     // [4 5 6 7]
s3 := s2[3:6]       // Error

Output :

       +---+---+---+---+---+---+---+---+---+---+   
 data  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |   
       +---+---+---+---+---+---+---+---+---+---+   
          0         2               5
               +---+---+---+---+---+---+---+---+
 s1            | 2 | 3 | 4 |   |   |   |   |   |   len = 3, cap = 8
               +---+---+---+---+---+---+---+---+
                    0          2                   6    7
                       +---+---+---+---+---+
 s2                    | 4 | 5 | 6 | 7 |   |       len = 4, cap = 5
                       +---+---+---+---+---+
                              0               3    4    5
                                   +---+---+---+
 s3                                | 7 | 8 | X |   error: slice bounds out of range
								   +---+---+---+

The new object still points to the original underlying array :

s := []int{
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := s[2:5]       // [2 3 4]
s1[2] = 100
s2 := s1[2:6]      // [100 5 6 7]
s2[3] = 200
fmt.Println(s)	   // [0 1 2 3 100 5 6 200 8 9]

5、append

towards slice Add data at the end , Return to new slice object .

Example :

func test4() {
    
	s := make([]int, 1, 5)
	s1 := append(s, 100)
	s2 := append(s1, 200, 300)

	fmt.Printf("the value of s: %v, the address of s: %p\n", s, &s)
	fmt.Printf("the value of s1: %v, the address of s1: %p\n", s1, &s1)
	fmt.Printf("the value of s2: %v, the address of s2: %p\n", s2, &s2)
	fmt.Printf("the original array is: %v\n", *(*[5]int)(unsafe.Pointer(&s[0])))	//  To print the original array , Use cast 
}

Output :

the value of s: [0], the address of s: 0xc000004480
the value of s1: [0 100], the address of s1: 0xc0000044a0
the value of s2: [0 100 200 300], the address of s2: 0xc0000044c0
the original array is: [0 100 200 300 0]

To put it simply , Is in the array[slice.high] Writing data .

Add another slice after slicing

Example :

func test8() {
    
	s1 := []int{
    1, 2, 3}
	s2 := []int{
    4, 5, 6}
	s3 := append(s1, s2...)
	s4 := append(s1[:1], s2...) //  take s2 Add to s1[0] At the end of 
	s5 := append(s1, s2[:2]...) //  take s2[0]、s2[1] Add to s1 At the end of 

	fmt.Printf("the value of s3: %v, the len: %d, the cap: %d\n", s3, len(s3), cap(s3))
	fmt.Printf("the value of s4: %v, the len: %d, the cap: %d\n", s4, len(s3), cap(s4))
	fmt.Printf("the value of s5: %v, the len: %d, the cap: %d\n", s5, len(s5), cap(s5))
}

Output :

the value of s3: [1 2 3 4 5 6], the len: 6
the value of s4: [1 4 5 6], the len: 4
the value of s5: [1 2 3 4 5], the len: 5


⼀ Dan goes beyond the original slice.cap Limit , Will reallocate the underlying array , Even if the original array is not filled .

Example :

func test5() {
    
	data := [...]int {
    0,1,2,3,4,5,6,7,8,9}
	s1 := data[:2:3]
	s2 := append(s1,100,200)
	fmt.Printf("the value of s1: %v, the address of s1[0]: %p\n", s1, &s1[0])
	fmt.Printf("the value of s2: %v, the address of s2[0]: %p\n", s2, &s2[0])
}

Output :

the value of s1: [0 1], the address of s1[0]: 0xc00000e140
the value of s2: [0 1 100 200], the address of s2[0]: 0xc00000a330

  As can be seen from the output ,append After s2 Reassigned the underlying array , And copy the data . If only ⼀ It's worth , It will not exceed s1.cap Limit , There will be no redistribution .
  Usually, the 2 Double the capacity to reallocate the underlying array . stay ⼤ When batch adding data , Suggest ⼀ Secondary distribution ⾜ enough ⼤ Space , To reduce memory allocation and data replication overhead . Or initialize ⾜ enough ⻓ Of len attribute , Change ⽤ Index number in ⾏ operation . Timely release no longer makes ⽤ Of slice object , Avoid holding expired arrays , cause GC ⽆ We can't recycle .


see cap Growth trend :

s := make([]int, 0, 1)
c := cap(s)
for i := 0; i < 50; i++ {
    
    s = append(s, i)
    if n := cap(s); n > c {
    
        fmt.Printf("cap: %d -> %d\n", c, n)
        c = n
    }
}

Output :

cap: 1 -> 2
cap: 2 -> 4
cap: 4 -> 8
cap: 8 -> 16
cap: 16 -> 32
cap: 32 -> 64

6、copy

function copy In two slice Copy data between , Copy ⻓ Du Yi len ⼩ Shall prevail . Two slice Can point to the same ⼀ The underlying array , Allow element intervals to overlap .

Example :

data := [...]int{
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s := data[8:]
s2 := data[:5]
copy(s2, s)          // dst:s2, src:s
fmt.Println(s2)
fmt.Println(data)

Output :

[8 9 2 3 4]
[8 9 2 3 4 5 6 7 8 9]

copy(dst, src)

Send the required data in time copy To compare ⼩ Of slice, In order to release super ⼤ No. the underlying array memory .

版权声明
本文为[baboon_ chen]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204210546351420.html