[Golang] Golang Advanced Series Tutorial--The difference between Go language array and slice

foreword

In the Go language, arrays and slices look similar, but in fact they have many differences. This article will talk about their differences.

Arrays and slices are two commonly used data structures. They can both be used to store a set of elements of the same type, but there are some important differences in the underlying implementation and usage.

The length of the array in Go is immutable, and Slice solves the demand for variable-length arrays. There are two main differences between them

array

An array is a collection of elements of the same data type. When defining an array, the length and element type need to be specified.
insert image description here

For example: [4]int represents an array containing four integers, and the size of the array is fixed. And the length is part of its type ([4]int and [5]int are different, incompatible types).
Array elements can be accessed by index, for example, the expression s[n] means to access the nth element, and the index starts from zero.

declaration and initialization

func main() {
    
    
    var nums [3]int   // 声明并初始化为默认零值
    var nums1 = [4]int{
    
    1, 2, 3, 4}  // 声明同时初始化
    var nums2 = [...]int{
    
    1, 2, 3, 4, 5} // ...可以表示后面初始化值的长度
    fmt.Println(nums)    // [0 0 0]
    fmt.Println(nums1)   // [1 2 3 4]
    fmt.Println(nums2)   // [1 2 3 4 5]
}

function parameters

If an array is used as a parameter of a function, what is actually passed is a copy of the array, not a pointer to the array. This also means that modifying the elements of the array in the function will not affect the original array.
insert image description here

package main

import (
    "fmt"
)

func Add(numbers [5]int) {
    
    
    for i := 0; i < len(numbers); i++ {
    
    
        numbers[i] = numbers[i] + 1
    }
    fmt.Println("numbers in Add:", numbers) // [2 3 4 5 6]
}

func main() {
    
    
    // declare and initialize the array
    var numbers [5]int
    for i := 0; i < len(numbers); i++ {
    
    
        numbers[i] = i + 1
    }

    Add(numbers)
    fmt.Println("numbers in main:", numbers) // [1 2 3 4 5]
}

slice

The usage scenarios of arrays are relatively limited, and slices are more commonly used.
A slice is a variable-length sequence of elements of the same type. It is a layer of encapsulation based on the array type. It is very flexible and supports automatic expansion.
insert image description here

A slice is a reference type that has three properties: pointer, length and capacity.

  • Pointer: Points to the first element that the slice can access.
  • Length: the number of elements in the slice.
  • Capacity: the number of elements between the start element of the slice and the last element of the underlying array.

The underlying source code is defined as follows:

type slice struct {
    
    
    array unsafe.Pointer
    len   int
    cap   int
}

declaration and initialization

func main() {
    
    
    var nums []int  // 声明切片
    fmt.Println(len(nums), cap(nums)) // 0 0
    nums = append(nums, 1)   // 初始化
    fmt.Println(len(nums), cap(nums)) // 1 1

    nums1 := []int{
    
    1,2,3,4}    // 声明并初始化
    fmt.Println(len(nums1), cap(nums1))    // 4 4

    nums2 := make([]int,3,5)   // 使用make()函数构造切片
    fmt.Println(len(nums2), cap(nums2))    // 3 5
}

function parameters

When a slice is used as a function parameter, unlike an array, if a function accepts a slice parameter, the changes it makes to the slice elements will be visible to the caller, similar to passing a pointer to the underlying array.

package main

import (
    "fmt"
)

func Add(numbers []int) {
    
    
    for i := 0; i < len(numbers); i++ {
    
    
        numbers[i] = numbers[i] + 1
    }
    fmt.Println("numbers in Add:", numbers) // [2 3 4 5 6]
}

func main() {
    
    
    var numbers []int
    for i := 0; i < 5; i++ {
    
    
        numbers = append(numbers, i+1)
    }

    Add(numbers)

    fmt.Println("numbers in main:", numbers) // [2 3 4 5 6]
}

Look at the above example again, change the parameter from an array to a slice, and the modification in the Add function will affect the main function.

Summarize

Finally, to sum up, you can also answer this way during the interview:

  • An array is a fixed-length data type whose length is determined at the time of definition and cannot be changed dynamically; a slice is a variable-length data type whose length can be empty when defined or an initial length can be specified.
  • The memory space of an array is allocated at the time of definition, and its size is fixed; the memory space of a slice is dynamically allocated at runtime, and its size is variable.
  • When an array is used as a function parameter, the function operates on a copy of the array and will not affect the original array; when a slice is used as a function parameter, the function operates on a reference to the slice, which will affect the original slice.
  • Slices also have the concept of capacity, which refers to the allocated memory space.

Guess you like

Origin blog.csdn.net/u011397981/article/details/132000207