This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

We’ve studied arrays in Golang before. An array is a sequence of numbered, fixed-length items of the same unique type, which can be any primitive type such as integer, string, or custom type. Conceptually, arrays are basically the same in all languages. Note that once an array is defined, its size cannot be changed. Take a look back: Learn Golang’s Array with me. In this article we’ll look at the upgrade “slicing” of arrays.

What is a slice

Go slices are abstractions of arrays. Go provides a flexible and powerful built-in type of slice (” dynamic array “). Slices are not fixed in length compared to arrays, and elements can be appented, which may increase the size of the slice.

Slicing is a convenient, flexible, and powerful wrapper. The slice itself doesn’t have any data. They are just references to existing arrays.

Slice compared with array, do not need to set the length, in [] do not set a value, relatively free.

Conceptually, a slice is like a structure that contains three elements:

  1. Pointer to the beginning of the array
  2. Length, the length of the slice
  3. The maximum length, which is the length from the start of the slice to the end of the array

Tip: Slicing is just a reference to an array, so it is very efficient. For example, when passing an array parameter to a function, use slicing instead of copying the array.

How do we distinguish between an array and a slice? Just see if there is an initial size in the definition syntax. If there is an initial size defined, that is, if there is a value in [], it is the data, otherwise it is the slice.

Definition section

var identifier []type
Copy the code

Slices do not need to specify length. Or use the make() function to create slices:

var slice0 []type = make([]type.len) can also be shortened to slice0 :=make([]type.len)
make([]T, length, capacity)
Copy the code

Initialize the

s[0] = 1
s[1] = 2
s[2] = 3
s :=[] int {1.2.3 } 
s := arr[startIndex:endIndex] 
Copy the code

Create a new slice (close in front and open in back) of length endindex-startIndex from the elements in arR from startIndex to endIndex-1

s := arr[startIndex:]  // By default, endIndex means that the last element is ignored, that is, until the end
Copy the code
s := arr[:endIndex]  // By default, startIndex means to ignore the first element and start from scratch
Copy the code
package main

import (  
    "fmt"
)

func main(a) {  
    a := [5]int{1.2.3.4.5}
    var b []int = a[1:4] //creates a slice from a[1] to a[3]
    fmt.Println(b)
}
Copy the code

Modify the section

Slice doesn’t have any data of its own. It’s just a representation of the underlying array. Any changes made to Slice will be reflected in the underlying array.

Example code:

package main

import (  
    "fmt"
)

func main(a) {  
    darr := [...]int{57.89.90.82.100.78.67.69.59} // Define an array
    dslice := darr[2:5] // Turn into slices
    fmt.Println("array before",darr)
    for i := range dslice {
        dslice[i]++
    }
    fmt.Println("array after",darr) 
}
Copy the code

Running result:

array before [57 89 90 82 100 78 67 69 59]  
array after [57 89 91 83 101 78 67 69 59]  
Copy the code

When multiple slices share the same underlying array, changes made to each element are reflected in the array.

Example code:

package main

import (  
    "fmt"
)

func main(a) {  
    numa := [3]int{78.79 ,80}
    nums1 := numa[:] // Slice the array
    nums2 := numa[:]
    fmt.Println("array before change 1",numa)
    nums1[0] = 100
    fmt.Println("array after modification to slice nums1", numa)
    nums2[1] = 101
    fmt.Println("array after modification to slice nums2", numa)
}
Copy the code

Running result:

array before change 1 [78 79 80]  
array after modification to slice nums1 [100 79 80]  
array after modification to slice nums2 [100 101 80]  
Copy the code

Len () and cap() functions

The length of a slice is the number of elements in the slice. The size of a slice is the number of elements in the underlying array from the index on which the slice was created.

Slices are indexable, and the length can be obtained by the len() method. Slices provide a way to calculate the capacity. Cap () can measure how long the slices can reach

package main

import "fmt"

func main(a) {
   var numbers = make([]int.3.5)

   printSlice(numbers)
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n".len(x),cap(x),x)
}
Copy the code

The results

len=3 cap=5 slice=[0 0 0]
Copy the code

Empty section

A slice defaults to nil and has a length of 0 before it is initialized. A nil slice cannot be used to store data.

package main

import "fmt"

func main(a) {
   var numbers []int

   printSlice(numbers)

   if(numbers == nil){
      fmt.Printf("Slice is empty.")}}func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n".len(x),cap(x),x)
}
Copy the code

The results

len=0 cap=0Slice =[] The slice is emptyCopy the code
package main

import "fmt"

func main(a) {
   /* Create slice */
   numbers := []int{0.1.2.3.4.5.6.7.8}   
   printSlice(numbers)

   /* Print the original slice */
   fmt.Println("numbers ==", numbers)

   /* Print subslices from index 1(included) to index 4(not included)*/
   fmt.Println("numbers[1:4] ==", numbers[1:4])

   /* The default lower limit is 0*/
   fmt.Println("numbers[:3] ==", numbers[:3])

   /* The default upper limit is len(s)*/
   fmt.Println("numbers[4:] ==", numbers[4:])

   numbers1 := make([]int.0.5)
   printSlice(numbers1)

   /* Print the subslice from index 0(included) to index 2(not included) */
   number2 := numbers[:2]
   printSlice(number2)

   /* Print subslices from index 2(included) to index 5(not included) */
   number3 := numbers[2:5]
   printSlice(number3)

}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n".len(x),cap(x),x)
}
Copy the code

The results

len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] = = [1 2 3]
numbers[:3] = = [0 1 2]
numbers[4:] = = [4 5 6 7 8]
len=0 cap=5 slice=[]
len=2 cap=9 slice=[0 1]
len=3 cap=7 slice=[2 3 4]
Copy the code

Append () and copy() functions

Append appends one or more elements to a slice and returns a slice of the same type as the slice. Similar to the Add method of the List class in Java.

The copy function copies elements from the source slice’s SRC to the target DST and returns the number of copied elements.

The append function changes the contents of the array referenced by a slice, affecting other slices that reference the same array. However, when there is no space left in slice (that is, (cap-len) == 0), a new array space is dynamically allocated at this point. The returned slice array pointer will point to this space, and the contents of the original array will remain unchanged; Other slices that reference this array are not affected. This sentence needs to be understood.

The following code describes the copy method from the copy slice and the Append method to append a new element to the slice

package main

import "fmt"

func main(a) {
   var numbers []int
   printSlice(numbers)

   /* Allow to append empty slices */
   numbers = append(numbers, 0)
   printSlice(numbers)

   /* Add an element */ to the slice
   numbers = append(numbers, 1)
   printSlice(numbers)

   /* Add multiple elements */ at the same time
   numbers = append(numbers, 2.3.4)
   printSlice(numbers)

   Numbers1 = double the size of the previous slice */
   numbers1 := make([]int.len(numbers), (cap(numbers))*2)

   /* Copy the contents of numbers1 */
   copy(numbers1,numbers)
   printSlice(numbers1)   
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n".len(x),cap(x),x)
}
Copy the code

The results

len=0 cap=0 slice=[]
len=1 cap=2 slice=[0]
len=2 cap=2 slice=[0 1]
len=5 cap=8 slice=[0 1 2 3 4]
len=5 cap=12 slice=[0 1 2 3 4]
Copy the code

Numbers1 and numbers are not related. Numbers1 does not change as numbers change. That is, the copy method does not establish a connection between two slices

package main

import "fmt"

func main(a)  {
    Slice = append(slice, elem1, elem2) Slice = Append (slice, anotherSlice...) * /
    s1 :=[] int{1.2.3.4}
    s2 :=[] int{5.6.7.8}
    // Mode 1:
    //for i:=0; i
    // s1 = append(s1,s2[i])
    / /}
    // Method 2:
    s1 = append(s1,s2...)
    fmt.Println(s1)

    fmt.Println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
    // Delete the contents of the slice
    s3 := []int{1.2.3.4.5.6.7.8.9}
    del:=3// The subscript of the element to be deleted
    //fmt.Println(s3[:del])
    //fmt.Println(s3[del+1:])
    s3 = append(s3[:del],s3[del+1:]...). fmt.Println(s3) }Copy the code

Use of the copy() method:

package main

import "fmt"

func main(a)  {
    /* copy(), slice is reference type, pass deep copy and shallow copy of address deep copy: copy of data value type is deep copy, basic type, array shallow copy: copy of address reference type default is shallow copy, slice, map */
     s1 := []int{1.2.3.4.5}
     s2 := s1
     fmt.Println(s1,s2)
     s2[0] =100
     fmt.Println(s1,s2)

     a := 100
     b := a
     fmt.Println(a,b)
     b = 200
     fmt.Println(a,b)
     fmt.Println("-- -- -- -- -- -- -- -- -- -- -- -- --")

     m:=[]int{1.2.3.4.5}
     n:=[]int{7.8.9}
     fmt.Println(m)
     fmt.Println(n)

     //copy(m,n) //copy the data in n to m
     //copy(n,m)// copy the data in m to n
     //copy(n,m[1:4]); // Copy (n,m[1:4])
     copy(n[1:],m[3:)// Copy the data in m from index 3 to the end after n from index 1
     fmt.Println(m)
     fmt.Println(n)


     s3 :=[]int{1.2.3.4}
     s4 := s3 / / shallow copy

     s5:=make([]int.4.4)
     copy(s5,s3)/ / copy
     fmt.Println(s4)
     fmt.Println(s5)
     s3[0] = 100
     fmt.Println(s4)
     fmt.Println(s5)

}
Copy the code

Expansion of slices

When adding data to slices, if the capacity is not exceeded, the data is added directly. If the capacity is exceeded, the data is automatically expanded (multiplied). Once the expansion occurs, the new array space will be returned, the original array space unchanged, that is, the new expanded array space operations will not be reflected in the original array space.

package main

import (
    "fmt"
)

func main(a)  {
/* Slice is called variable length array, the length is not fixed len (), cap() when adding data to slice, if the capacity is not exceeded, add it directly, if the capacity is exceeded, automatically expand (multiply) 3-->6-->12-->24-->48 4-->8-->16-->32 */
    arr := [10]int{1.2.3.4.5.6.7.8.9.10}
    fmt.Println(arr)
    fmt.Printf("%p\n",&arr) // Prints the address of the array itself

    s1 := arr[:5]
    fmt.Println(s1)
    fmt.Printf("%p, length: %d, capacity: %d\n",s1,len(s1),cap(s1)) // Length: 5, capacity: 10
    s2 := arr[2:7]
    fmt.Println(s2)
    fmt.Printf("%p, length: %d, capacity: %d\n",s2,len(s2),cap(s2)) // Length: 5, capacity: 8

    // Modify the slice's data. In fact, modify the slice's underlying array data.
    // Causes all data pointing to slices of the array to change.
    s1[3] = 100
    fmt.Println(arr)
    fmt.Println(s1)
    fmt.Println(s2)

    // Append (), append data
    s1 = append(s1,1.1.1.1) // S1: length: 5, capacity: 10
    fmt.Println(arr) //[1 2 3 100 5 1 1 1 1 1 10]
    fmt.Println(s1) //[1 2 3 100 5 1 1 1 1 1]
    fmt.Println(s2) //[3 100 5 1 1]

    // Append to the underlying array to which the slice is pointing, when the expansion is involved
    //s2:len5,cap8
    s2= append(s2, 2.2.2.2.2)
    // Change the underlying array to which s2 points
    fmt.Println(arr)//[1 2 3 100 5 1 1 1 1 1 10]
    fmt.Println(s1) //[1 2 3 100 5 1 1 1 1 1]
    fmt.Println(s2) //[3 100 5 1 1 2 2 2 2 2 2

}
Copy the code

Slices are reference types

package main

import "fmt"

func main(a) {
    /* Value types: array, int, float, string, bool; /* value types: array, int, float, string, bool

     arr1 :=[4]int{1.2.3.4}
     arr2 := arr1// The data is passed
     fmt.Println(arr1,arr2)
     arr2[0] =100
     fmt.Println(arr1,arr2)

     s1 :=[]int{1.2.3.4}
     fmt.Println(s1)

     s2 := s1 // The delivery address
     fmt.Println(s2)
     s2[0] =100
     fmt.Println(s1,s2)
}
Copy the code

Running result:

[1 2 3 4] [1 2 3 4]
[1 2 3 4] [100 2 3 4]
[1 2 3 4]
[1 2 3 4]
[100 2 3 4] [100 2 3 4]
Copy the code