This is the 8th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

7.3 an array

7.3.1 overview

An array is a collection of data of the same type. Each piece of data in an array is called an element, and the number of elements in an array is called the length of the array.

 

The array length must be constant and part of the type. [2]int and [3]int are different types.

var n int = 10
var a [n]int  //err, non-constant array bound n
var b [10]int //ok
Copy the code

7.3.2 Manipulating arrays

Each element of an array can be accessed by indexing, which ranges from 0 to the array length minus 1.

var a [10]int
for i := 0; i < 10; i++ {
    a[i] = i + 1
    fmt.Printf("a[%d] = %d\n", i, a[i])
}

// Range has two return values. The first return value is the array index of the element, and the second return value is the element value
for i, v := range a {
    fmt.Println("a[", i, "] =", v)
}
Copy the code

The built-in functions len(length) and cap(capacity) both return the array length (number of elements) :

a := [10]int{}
fmt.Println(len(a), cap(a))//10 10
Copy the code

Initialization:

a := [3]int{1.2}           // Uninitialized elements have a value of 0
b := [...]int{1.2.3}      // The array length is determined by the initialization value
c := [5]int{2: 100.4: 200} // The element is initialized by the index number, and the uninitialized element is 0
fmt.Println(a, b, c)        //[1 20] [1 2 3] [0 0 100 0 200]

// Support multi-dimensional arrays
d := [4] [2]int{{10.11}, {20.21}, {30.31}, {40.41}} e := [...] [2]int{{10.11}, {20.21}, {30.31}, {40.41}} // The second dimension cannot be written "...".
f := [4] [2]int{1: {20.21}, 3: {40.41}}
g := [4] [2]int{1: {0: 20}, 3: {1: 41}}
fmt.Println(d, e, f, g)
Copy the code

You can use == or! Between arrays of the same type. =, but you can’t use < or >, and you can assign values to each other: \

a := [3]int{1.2.3}
b := [3]int{1.2.3}
c := [3]int{1.2}
fmt.Println(a == b, b == c) //true false

var d [3]int
d = a
fmt.Println(d) / / [1 2 3]
Copy the code

7.3.3 Passing arrays between functions

Passing arrays between functions is an expensive operation in terms of memory and performance. When passing variables between functions, they are always passed as values. If this variable is an array, that means that the entire array, no matter how long it is, will be copied in full and passed to the function.

func modify(array [5]int) {
    array[0] = 10 // Attempts to modify the first element of the array
    //In modify(), array values: [10 2 3 4 5]
    fmt.Println("In modify(), array values:", array)
}
 
func main(a) {
    array := [5]int{1.2.3.4.5} // Define and initialize an array
    modify(array)                  // Pass it to a function and attempt to modify the contents of the array inside the function itself
    //In main(), array values: [1 2 3 4 5]
    fmt.Println("In main(), array values:", array)} Array pointer as function argument:func modify(array *[5]int) {
    (*array)[0] = 10
    //In modify(), array values: [10 2 3 4 5]
    fmt.Println("In modify(), array values:", *array)
}
 
func main(a) {
    array := [5]int{1.2.3.4.5} // Define and initialize an array
    modify(&array)                 // Array pointer
    //In main(), array values: [10 2 3 4 5]
    fmt.Println("In main(), array values:", array)
}
Copy the code

7.3.4 Array Pointers

An int needs 8 villas, 8 ints need 64 villas, the same principle, only need to tell others the first address, and then the next 64 sets are mine, how do others know 64? Because you can derive that from the type and the length.

package main // There must be a main package
import "fmt"
func modify(p *[5]int) {
    (*p)[0] = Awesome!
    fmt.Println("modify *a = ", *p) //modify *a = [666 2 3 4 5]
}
func main(a) {
    a := [5]int{1.2.3.4.5} / / initialization
    modify(&a) // Address delivery
    fmt.Println("main: a = ", a) //main: a = [666 2 3 4 5]
}
Copy the code

7.4 slice

7.4.1 overview

Disadvantages of arrays: the length cannot be changed after the definition; Arrays are value types, and each pass will produce a copy.

Obviously, this data structure cannot fully meet the real needs of developers. The Go language provides array slices to make up for the lack of arrays.

Slices are not arrays or array Pointers; they refer to array fragments through internal Pointers and related properties to implement variable-length schemes.

Slice is not really a dynamic array, but a reference type. A slice always points to an underlying array. A slice declaration can be similar to an array declaration, but does not require a length.

7.4.2 Creating and initializing slices

The difference between slice and array: When declaring an array, specify the length of the array in square brackets or use… The length is computed automatically, and when a slice is declared, there are no characters inside the square brackets.

var s1 []int Declare slice is the same as declare array, but the length is missing. This is nil
s2 := []int{}

Make ([]T, length, capacity) // Make ([]T, length, capacity
var s3 []int = make([]int.0)
s4 := make([]int.0.0)

s5 := []int{1.2.3} // Create slice and initialize
Copy the code

Note: Make can only create slice, map, and channel, and returns an initial value (non-zero).

Tip: If the array size can be estimated in advance, it is recommended to create slices based on the estimated size to avoid the performance cost of data copy caused by dynamic array size adjustment by slices.

7.4.3 Section Operations

7.4.3.1 Slice interception

operation meaning
s[n] The item in slice S with index position n
s[:] The slice obtained from the index position 0 to len(s)-1 of slice S
s[low:] The slice obtained from the index position low to len(s)-1 of slice S
s[:high] Select * from slice s from index position 0 to high, len=high
s[low:high] Select * from slice s from index position low to high, len=high-low
s[low:high:max] For slice s obtained from index position low to high, len=high-low, cap=max-low
len(s) Length of slice s, always <=cap(s)
cap(s) Size of slice s, always >=len(s)

 

Example:

    array := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

 

operation The results of len cap instructions
array [:6:8] [0 1 2 3 4 5] 6 8 Omit the low,
array[5:] [5 6 7 8 9] 5 5 Omit high, Max
array[:3] [0, 1, 2] 3 10 Omit high, Max
array[:] [0 1 2 3 4 5 6 7 8 9] 10 10 All omit

 

7.4.3.2 Slicing and underlying array relationships

s := []int{0.1.2.3.4.5.6.7.8.9}

s1 := s[2:5]       / / [2, 3, 4]
s1[2] = 100        // Modify slice an element to change the underlying array
fmt.Println(s1, s) //[2 3 100] [0 1 2 3 100 5 6 7 8 9]

s2 := s1[2:6] // The new slice still points to the underlying array [100 5 6 7]
s2[3] = 200
fmt.Println(s2) / / [100 5 6 200]

fmt.Println(s) //[0 1 2 3 100 5 6 200 8 9]
Copy the code

7.4.3.3 Built-in functions

1) append

The append function adds data to the end of slice and returns a new slice object:

var s1 []int // Create nil switch
//s1 := make([]int, 0)
s1 = append(s1, 1)       // Append 1 element
s1 = append(s1, 2.3)    // Append 2 elements
s1 = append(s1, 4.5.6) // Append 3 elements
fmt.Println(s1)          //[1 2 3 4 5 6]

s2 := make([]int.5)
s2 = append(s2, 6)
fmt.Println(s2) //[0 0 0 0 0 6]

s3 := []int{1.2.3}
s3 = append(s3, 4.5)
fmt.Println(s3)//[1 2 3 4 5]
Copy the code

The append function intelligently increases the size of the underlying array. Once the size of the underlying array exceeds the original size, it usually reallocates the underlying array at twice that size and copies the original data:

func main() {
    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
        }
    }
    /*
        cap: 1 -> 2
        cap: 2 -> 4
        cap: 4 -> 8
        cap: 8 -> 16
        cap: 16 -> 32
        cap: 32 -> 64
    */
}
Copy the code
  1. copy

The copy function copies data between two slis with a length smaller than len. Both slis can point to the same underlying array.

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

7.4.4 Slice as function parameter

func test(s []int) { // Slice as function parameter
    s[0] = - 1
    fmt.Println("test : ")
    for i, v := range s {
        fmt.Printf("s[%d]=%d, ", i, v)
        //s[0]=-1, s[1]=1, s[2]=2, s[3]=3, s[4]=4, s[5]=5, s[6]=6, s[7]=7, s[8]=8, s[9]=9,
    }
    fmt.Println("\n")}func main(a) {
    slice := []int{0.1.2.3.4.5.6.7.8.9}
    test(slice)
 
    fmt.Println("main : ")
    for i, v := range slice {
        fmt.Printf("slice[%d]=%d, ", i, v)
        //slice[0]=-1, slice[1]=1, slice[2]=2, slice[3]=3, 
        //slice[4]=4, slice[5]=5, slice[6]=6, slice[7]=7, slice[8]=8, slice[9]=9,
    }
    fmt.Println("\n")}Copy the code

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.

7.4.5 Differences between Cap and Len

In simple terms, len(sli) indicates how many elements are visible (that is, the number of elements seen by printing the element directly), and cap(sli) indicates how many elements are all visible. For example:

arr := []int{2, 3, 5, 7, 11, 13}
sli := arr[1:4]
fmt.Println(sli) //[3 5 7]
fmt.Println(len(sli))//3
fmt.Println(cap(sli))//5
Copy the code

7.4.6 Slicing and underlying arrays

Multiple slices can be generated from the same array. When you modify slice A, the underlying array changes directly, and if slice B happens to refer to the same place, it also changes.

Import "FMT" func main() {a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} s1 := a[2:5] s2 := s1[1:7] s1[1] = 666 fmt.Println("s1 = ", s1) //s1 = [2 666 4] fmt.Println("a = ", a) //a = [0 1 2 666 4 5 6 7 8 9] s2[1] = 777 fmt.Println("s2 = ", s2) //s2 = [666 777 5 6 7 8] fmt.Println("a = ", a) //a = [0 1 2 666 777 5 6 7 8 9] fmt.Println("s1 = ", s1)//s1 = [2 666 777] }Copy the code

So you can see that slicing is actually taking a piece of the underlying array through a pointer.

Tip: You can define slices from an array, or you can define new slices from slices.