go array and slice [golang notes]

Posted by rubric on Fri, 04 Feb 2022 09:59:27 +0100

1, Array

An array is a collection of data of the same type. Each data contained in the array is called an array element. This type can be the original type of meaning, such as int, string, etc., or a user-defined type. The number of elements contained in an array is called the length of the array. In Golang, array is a data type with a fixed length, and the length of array is a part of the type, that is, [5]int and [10]int are two different types. Another feature of array in Golang is the continuity of memory occupation, that is, the elements in the array are allocated to continuous memory addresses, so the speed of index group elements is very fast.

The type corresponding to the array is slice. Slice is a dynamic sequence that can grow and shrink, and its function is more flexible. However, if you want to understand the working principle of slice, you need to understand the array first, so this section mainly explains the use of array.

array define

var Array variable name [Number of elements] T

Examples

// The length of the array is part of the type
var arr1 [3]int
var arr2 [4]string
fmt.Printf("%T, %T \n", arr1, arr2)

// The first method of array initialization
var arr3 [3]int
arr3[0] = 1
arr3[1] = 2
arr3[2] = 3
fmt.Println(arr3)

// The second method is to initialize the array
var arr4 = [4]int {10, 20, 30, 40}
fmt.Println(arr4)

// The third array initialization method automatically infers the array length
var arr5 = [...]int{1, 2}
fmt.Println(arr5)

// The fourth way to initialize an array is to specify a subscript
a := [...]int{1:1, 3:5}
fmt.Println(a)

Traversal array

Method 1

// The fourth way to initialize an array is to specify a subscript
a := [...]int{1:1, 3:5}
for i := 0; i < len(a); i++ {
	fmt.Print(a[i], " ")
}

Method 2

// The fourth way to initialize an array is to specify a subscript
a := [...]int{1:1, 3:5}
for _, value := range a {
    fmt.Print(value, " ")
}

Value type of array

Array is a value type. Assignment and reference will assign the entire array, so changing the value of the copy will not change its own value

// array
var array1 = [...]int {1, 2, 3}
array2 := array1
array2[0] = 3
fmt.Println(array1, array2)

For example, in the above code, after we assign values to the array, when we change the values in the array, we find that the results are as follows

[1 2 3] [3 2 3]

This shows that the array in golang is a value type, not a reference data type like java

Slice definition (reference type)

In golang, the definition of slice is similar to that of array, but it should be noted that slice is a reference data type, as shown below

// Slice definition
var array3 = []int{1,2,3}
array4 := array3
array4[0] = 3
fmt.Println(array3, array4)

We change the first slice element and see the final effect

[3 2 3] [3 2 3]

Two dimensional array

Go language supports multi-dimensional arrays. Here we take two-dimensional arrays as an example (arrays are nested):

var Array variable name [Number of elements][Number of elements] T

Examples

// Two dimensional array
var array5 = [2][2]int{{1,2},{2,3}}
fmt.Println(array5)

Array traversal

Traversal of two-dimensional data group

// Two dimensional array
var array5 = [2][2]int{{1,2},{2,3}}
for i := 0; i < len(array5); i++ {
    for j := 0; j < len(array5[0]); j++ {
        fmt.Println(array5[i][j])
    }
}

Traversal mode 2

for _, item := range array5 {
    for _, item2 := range item {
        fmt.Println(item2)
    }
}

Type derivation

In addition, we can also use type derivation when creating arrays, but we can only use one

// Two dimensional array (correct writing)
var array5 = [...][2]int{{1,2},{2,3}}

Wrong writing

// Two dimensional array
var array5 = [2][...]int{{1,2},{2,3}}

Complete code

package main

import "fmt"

func main() {
	// The length of the array is part of the type
	var arr1 [3]int
	var arr2 [4]string
	fmt.Printf("%T, %T \n", arr1, arr2)

	// The first method of array initialization
	var arr3 [3]int
	arr3[0] = 1
	arr3[1] = 2
	arr3[2] = 3
	fmt.Println(arr3)

	// The second is the violation of initializing arrays
	var arr4 = [4]int {10, 20, 30, 40}
	fmt.Println(arr4)

	// The third array initialization method automatically infers the array length
	var arr5 = [...]int{1, 2}
	fmt.Println(arr5)

	// The fourth way to initialize an array is to specify a subscript
	a := [...]int{1:1, 3:5}
	fmt.Println(a)

	for i := 0; i < len(a); i++ {
		fmt.Print(a[i], " ")
	}

	for _, value := range a {
		fmt.Print(value, " ")
	}

	fmt.Println()
	// Value type reference type
	// Both basic data types and arrays are value types
	var aa = 10
	bb := aa
	aa = 20
	fmt.Println(aa, bb)

	// array
	var array1 = [...]int {1, 2, 3}
	array2 := array1
	array2[0] = 3
	fmt.Println(array1, array2)

	// Slice definition
	var array3 = []int{1,2,3}
	array4 := array3
	array4[0] = 3
	fmt.Println(array3, array4)

	// Two dimensional array
	var array5 = [...][2]int{{1,2},{2,3}}
	for i := 0; i < len(array5); i++ {
		for j := 0; j < len(array5[0]); j++ {
			fmt.Println(array5[i][j])
		}
	}

	for _, item := range array5 {
		for _, item2 := range item {
			fmt.Println(item2)
		}
	}
}

2, Slice

Why use slicing

A Slice is a variable length sequence of elements of the same type. It is a layer of encapsulation based on array type.
It is very flexible and supports automatic capacity expansion.

A slice is a reference type whose internal structure contains address, length, and capacity.

The basic syntax for declaring slice types is as follows:

var name [] T

Of which:

  • Name: indicates the variable name
  • T: Represents the element type in the slice

give an example

// Declare slicing. Removing the length is slicing
var slice = []int{1,2,3}
fmt.Println(slice)

Understanding of nil

When you declare a variable but haven't assigned a value, golang will automatically assign a default value of zero to your variable. This is the zero value for each type.

  • bool: false
  • numbers: 0
  • string: ""
  • pointers: nil
  • slices: nil
  • maps: nil
  • channels: nil
  • functions: nil

Nil means null, that is, the default value of array initialization is nil

var slice2 [] int
fmt.Println(slice2 == nil)

Operation results

true

Traversal of slices

The traversal of slices is the same as that of arrays

var slice = []int{1,2,3}
for i := 0; i < len(slice); i++ {
    fmt.Print(slice[i], " ")
}

Defining slices based on arrays

Since the bottom layer of the slice is an array, we can define the slice based on the array

// Defining slices based on arrays
a := [5]int {55,56,57,58,59}
// Get all the values of the array and return a slice
b := a[:]
// Gets the specified slice from the array
c := a[1:4]
// Get data before subscript 3 (excluding 3)
d := a[:3]
// Get the data after subscript 3 (including 3)
e := a[3:]

Operation results

[55 56 57 58 59]
[55 56 57 58 59]
[56 57 58]
[55 56 57]
[58 59]

Similarly, we can not only slice the array, but also slice it in the slice

Length and capacity of slices

The slice has its own length and capacity. We can calculate the length by using the built-in len) function and use the built-in cap ()
Function to find the capacity of the slice.

The length of the slice is the number of elements it contains.

The capacity of a slice is the number from its first element to the end of its underlying array element. The length and capacity of slice s can be obtained by the expressions len (s) and cap (s).

give an example

// Length and capacity
s := []int {2,3,5,7,11,13}
fmt.Printf("length%d capacity%d\n", len(s), cap(s))

ss := s[2:]
fmt.Printf("length%d capacity%d\n", len(ss), cap(ss))

sss := s[2:4]
fmt.Printf("length%d capacity%d\n", len(sss), cap(sss))

Operation results

Length 6 capacity 6
 Length 4 capacity 4
 Length 2 capacity 4

Why is the last capacity different? Because we know that after slicing, SSS = [5,7], so the length of the slice is 2, but because the capacity is from the position of 2 to the end, it is 4

The essence of slicing

The essence of slicing is to encapsulate the underlying array, which contains three information

  • Pointer to the underlying array
  • Length of slice (len)
  • Slice capacity (cap)

Using the make function to construct slices

We create slices based on arrays above. If we need to dynamically create a slice, we need to use the built-in make function. The format is as follows:

make ([]T, size, cap)

Of which:

  • T: Element type of slice
  • size: the number of elements in the slice
  • cap: capacity of slice

give an example:

// The make() function creates a slice
fmt.Println()
var slices = make([]int, 4, 8)
//[0 0 0 0]
fmt.Println(slices)
// Length: 4, capacity: 8
fmt.Printf("Length:%d, capacity%d", len(slices), cap(slices))

It should be noted that there is no way to expand the slice capacity through subscript in golang. If you need to expand the capacity, you need to use append

slices2 := []int{1,2,3,4}
slices2 = append(slices2, 5)
fmt.Println(slices2)
// Output results [1 2 3 4 5]

You can also merge two slices at the same time

// Merge slices
slices3 := []int{6,7,8}
slices2 = append(slices2, slices3...)
fmt.Println(slices2)
// Output results [1 2 3 4 5 6 7 8]

It should be noted that the slice will have a capacity expansion operation. When the elements cannot be stored, the original capacity will be doubled

Use the copy() function to copy slices

As we know earlier, slicing refers to data types

  • Value type: when changing the copy of the variable, the variable itself will not be changed
  • Reference type: when changing the value of the variable copy, the value of the variable itself will be changed

If we need to change the value of the slice without affecting the original slice, we need to use the copy function

// Slices to be copied
var slices4 = []int{1,2,3,4}
// Use the make function to create a slice
var slices5 = make([]int, len(slices4), len(slices4))
// Copy slice value
copy(slices5, slices4)
// Modify slice
slices5[0] = 4
fmt.Println(slices4)
fmt.Println(slices5)

The running result is

[1 2 3 4]
[4 2 3 4]

Delete values in slices

There is no special method to delete slice elements in Go language. We can use the characteristics of slice itself to delete elements. The code is as follows

// Delete values in slices
var slices6 = []int {0,1,2,3,4,5,6,7,8,9}
// Delete value with subscript 1
slices6 = append(slices6[:1], slices6[2:]...)
fmt.Println(slices6)

Operation results

[0 2 3 4 5 6 7 8 9]

Topics: Go Back-end