Location>code7788 >text

Go Must Know: Exploring Arrays and Slices in the Go LanguageDeeper Understanding of Sequential Collections

Popularity:427 ℃/2024-09-03 10:27:07

At the end of this article, there is a group to share the interview experience

Among the Go language's rich set of data types, arrays and slices are powerful tools for working with ordered collections of data, allowing developers to store and manage multiple elements of the same type in contiguous blocks of memory. Arrays and slices play a crucial role, both for performance optimization when working with large amounts of data and for implementing algorithms that require data structures.

Arrays in Go

In the Go language, an array is a basic data structure used to store a collection of elements of the same type. Arrays differ from slices in that the length of an array is fixed, immutable once declared, and part of the array's type definition, which means that the type of an array includes not only the type of its elements, but also its length.

define

When defining an array, you must specify the type of elements and the length of the array. For example.[3]bool Represents a boolean array of length 3;[4]int Represents an integer array of length 4.

var a1 [3]bool
var a2 [4]int

("a1:%T\na2:%T\n", a1, a2)

The printout is as follows:

Array initialization

default value

When defining an array without initialization, the default elements are zero values: false for bool types, 0 for integer and floating point types, and the empty string " " for strings.

var a1 [3]bool 
var a2 [4]int

(a1, a2)

The printout is as follows:

Initialization method 1: Define the value in curly brackets and the length.

The simplest way to initialize:

var a1 [3]bool 
a1 = [3]bool{true,false,false}
(a1)

The printout is as follows:

Initialization method 2: Automatically determine the length of the array based on the initial value.

Write the length in center brackets, when the number of values defined is smaller than the length, it will be complemented with the default value, such as 0, false, "".

a8 := [10]int{0, 1, 2, 3, 4, 5, 6, 7} //7 will be followed by a 0 patch
(a8)

Print result: [0 1 2 3 4 5 6 7 0 0].

[...] usage:[...] When setting the length of an array, the length of the array is automatically determined based on the initial value.

aa := [...] int{0, 1, 2, 3, 4, 5, 6, 7} //[...] Automatically determine the length of the array based on the initial value
(aa)

Print result: [0 1 2 3 4 5 6 7].

Initialization method 3: Initialization by index

Specifies the value corresponding to the index. Unspecified indexed values are filled with default values, such as 0, false, "".

a3 := [5]int{0: 1, 4: 2} //initialize by index
(a3)

Print result: [1 0 0 0 2].

retrieve a value

Iterate over the array

You can use a standardfor loop to iterate through each element of the array. This method requires you to manually manage the index variable and use it to access the elements in the array.

For i Loop over the array:

citys := [...] string{"Beijing", "Shanghai", "Shenzhen"} // indexed from 0 to 2
// Iterate by index
for i := 0; i < len(citys); i++ {
   (citys[i])
}

The printout is as follows:

for range is a more concise syntax for traversing arrays or slices.for range The loop automatically generates indexes and element values, making the traversal process easier.

citys := [...] string{"Beijing", "Shanghai", "Shenzhen"} //indexed from 0 to 2
for i, city := range citys {
   ("key value: %d city is: %v\n", i, city)
}

The printout is as follows:

multidimensional array

define

Let's take the example of a two-dimensional array, such as the definition of the[[1 2 3][4 5 6]] How would one define such a two-dimensional array?

Examples are shown below:

  1. The first unit of length in the following code, [2], indicates how many elements are in the two-dimensional array;

  2. The second length unit, [3], indicates how many elements are in the subset array;

  3. On initialization: variable = array type {}.

// Define multi-dimensional arrays
var a11 [2][3]int

//Initialize the multidimensional array
a11 = [2][3]int{
   [3]int{1, 2, 3}, //Define the multidimensional array.
   [3]int{4, 5, 6}, //note: this last one should also be comma-separated
}

(a11)

The printout is as follows:

retrieve a value

Iteration over multidimensional arrays:

// Define a multidimensional array
var a11 [2][3]int

//Initialize the multidimensional array
a11 = [2][3]int{
   [3]int{1, 2, 3}, //Define the multidimensional array.
   [3]int{4, 5, 6}, //note: this last one should also be comma-separated
}

// double for range traversal values
for _, v1 := range a11 {
   (v1)
   for _, v2 := range v1 {
      (v2)
   }
}

The printout is as follows:

Array characteristics: value type not reference type

We find that assigning b 1 to b 2 and then modifying the value of b 2 does not change the value of b 1. This is the biggest difference between arrays and slices, and we suggest that you compare and learn about slices again.

b1 := [3]int{1, 2, 3}
b2 := b1
b2[0] = 100
(b1,b2)

The printout is as follows:

To summarize: this means that Go's arrays are value types, not reference types.b2:=b1 operation opens up new memory space for b 2 instead of referencing b 1's memory address.

Arrays in action

Sum all elements of the array cArray[1, 3, 5, 7, 8]:

cArray := [...] int{1, 3, 5, 7, 8}
r := 0
for _, i2 := range cArray {
   r += i2
}
("The sum result is: %v", r)

Print results:The sum result is: 24

Find the subscripts in the cArray array that sum to 8, such as [0 3] and [1 2]:

for i := 0; i < len(cArray); i++ {
   for j := 0; j < i; j++ {
      if cArray[i]+cArray[j] == 8 {
         ("The subscripts that match are: %v,%v \n", j, i)
      }
   }
}

The printout is as follows:

Slicing in Go

Slices are distinguished from arrays by being reference types, not value types. Arrays are of fixed length, while slices are of variable length, and my understanding is that a slice is a reference to a fragment of an array.

define

A slice is a flexible sequence type that is based on arrays; unlike arrays, slices are variable in length and are not included in the type definition. For example.[]int represents a slice holding elements of type integer.[]string Represents a slice holding elements of type string.

var s1 []int
var s2 []string
(s1, s2)
(s1 == nil) //true is null no memory space opened
(s2 == nil) //true

The printout is as follows:

Ans: This meanss1 cap (a poem)s2 They do not currently point to any actual memory space; they are "empty" slices. In Go, when slices are declared but not initialized, their default values arenilnil is a special value that means "none" or "null", which for slices means that the slice has no underlying array and no length or capacity. Therefore, attempting to access or modify anil Sliced elements will cause a runtime error.

Declare and initialize

We can initialize it while declaring it:

var s1 = []int{1, 2, 3}
var s2 = []string{"Beiyuan", "Changyang", "Wangjing"}
(s1, s2)
(s1 == nil) //false
(s2 == nil) //false

The printout is as follows:

Ans: Initialization was successful.s1 cap (a poem)s2 None of the values ofnil

Length and capacity

Use len (), cap () to get the length and capacity of the slice respectively.

("len(s1):%d cap(s1):%d\n", len(s1), cap(s1))
("len(s2):%d cap(s2):%d\n", len(s2), cap(s2))

The printout is as follows:

Ans: As we expected, the length and capacity are both 3.

Getting slices from arrays

I've already mentioned the relationship between arrays and slices in the opening post, so here's a little further:

  1. Slicing is essentially manipulating arrays, except that arrays are of fixed length and slices are of variable length;

  2. Slice is a reference type, can be understood as a reference to a fragment of the array; and the array is a value type, the array A assigned to the array B, will open up a new memory space for the array B, modify the value of the array B and will not affect the array A;

  3. And slices as reference types, pointing to the same memory address, are going to affect each other.

// Define an array
a1 := [...] int{1, 2, 3, 4, 5, 6, 7, 8, 9}
s3 := a1[0:4] //based on an array cut [0:4] left contains right does not contain i.e. [1,2,3,4]
(s3)

The printout is as follows:

Attention:a1[0:4] is a slice expression that is based on the arraya1 A new slice is created containing the array with the index from the0 until (a time)3 in the above example is {1, 2, 3, 4}.

More cutting examples

Slices provide a variety of cutting styles that allow you the flexibility to manipulate and access partial elements of arrays or other slices. Here are some examples of common slice cutting methods:

a1 := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
s4 := a1[2:4] //[3 4]
s5 := a1[:4] //[1 2 3 4]
s6 := a1[2:] //[3 4 5 6 7 8 9]
s7 := a1[:]  //[1 2 3 4 5 6 7 8 9]
(s4)
(s5)
(s6)
(s7)

The printout is as follows:

Ans: Slicing operations4 Starting at index 2 and going to index 4 (left closed, right open), thes5 The default is to start intercepting at index 0.s6 intercepts to the last element, whiles7 The index is omitted to indicate that all elements are fetched, and all these slicing operations follow the principle of left inclusion and right exclusion.

Length and volume of slices

The length of a slice is well understood to be the number of elements.

The capacity of slicing we focus on understanding:The length from the first element of the slice to the last element of the array in the underlying array referenced by the slice is the capacity of the slice ****.

I'll draw a picture:

Let's look at the following example again to understand it well:

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

s5 := a1[:4] //[1 2 3 4]
s6 := a1[2:] //[3 4 5 6 7 8 9]
s7 := a1[:]  //[1 2 3 4 5 6 7 8 9]

("len(s5):%d cap(s5):%d\n", len(s5), cap(s5)) //4 9
("len(s6):%d cap(s6):%d\n", len(s6), cap(s6)) //7 7
("len(s7):%d cap(s7):%d\n", len(s7), cap(s7)) //9 9

The printout is as follows:

Ans: a 1 is an array of length 9 and capacity 9 with values from 1 to 9.

S 5/s 6/s 7 are all slices obtained by cutting array a 1.

The length of S 5 is 4, because there are only 4 elements, 1 2 3 4, and the capacity is 9, because the slicing of s 5 starts from the beginning of the array: the first element is 1, and the last element of the underlying array a 1 of s 5 is 9, and the total number of elements from 1 to 9 is 9. Therefore, the capacity of s 5 is 9.

The length of S 6 is 7, because the elements of s 6 are the 7 elements from 3 to 9; the capacity is also 7, because the last element of the underlying array of s 5 is 9, and there are a total of 7 elements from 3 to 9, so the capacity of s 6 is 7.

S 7 is better understood, the length and capacity is 9, guys understand it by themselves.

Slicing and re-slicing.

We can perform re-slicing operations on the slices, e.g., slicing the data again for testing against the above:

s8 := s6[3:]
//the value of s8 is: 6 7 8 9
("len(s8):%d cap(s8):%d\n", len(s8), cap(s8)) //4 4

The printout is as follows:

Parsing: We know that we can slice again on the slice can be, as for the length and container we understand the above example, this output is expected.

Slicing characteristics: reference types are not value types

Let's give an example to show that slices are reference types:

// Define the array
a1 := [...] int{1, 2, 3, 4, 5, 6, 7, 8, 9}
// Cut the array into slices s6
s6 := a1[2:] //[3 4 5 6 7 8 9]
// slice again, assign to s8
s8 := s6[3:] //[6 7 8 9]
// Modify the original array by changing the value of subscript 2 from 3 to 333
a1[2] = 333
//print s6 and find that the 3 in s6 has also changed to 333
("s6:", s6) //[333 4 5 6 7 8 9]
// Because s8 is sliced based on s6, let's test the slicing and re-slicing of the references passed to
("s8:", s8) //[6 7 8 9]
// We change the value of the original array subscripted 5 from 6 to 666
a1[5] = 666
// Print the s8 slice and get the result 6 also changed to 666
("s8:", s8) //[666 7 8 9]

The printout is as follows:

Parsing:From this we know unequivocally that slices are reference types, and when the underlying array changes, the value changes whether it is a slice, or a slice and slice again. This is because they use a block of memory that references a memory address.

summarize

Arrays and slices in the Go language each have their own characteristics:

  1. While arrays are suitable for scenarios where the length is fixed and known, slices offer greater flexibility, especially when dealing with dynamically sized collections of data;

  2. Arrays, as value types, will copy data during assignment and function passing, ensuring data independence; while slices, as reference types, may point to the same underlying array for multiple slice variables, so special attention should be paid to the impact on the underlying data during operation.

Welcome ❤

We got a free interview questions sharing group to share and brush up on our progress together.

Maybe it will enable you to brush up on the latest interview questions for your intended company.

Interested friends can add my WeChat: wangzhongyang1993, note: [blog garden].