Mastering Multidimensional Arrays in Go

GoGoBeginner
Practice Now

Introduction

In the previous section, we learned about the basic usage of arrays.

So what types of elements can be in an array?

In Go, the elements in an array can be of any primitive type, such as integers, strings, or custom types.

And what happens if the elements in an array are arrays?

Then we have a multidimensional array:

Multidimensional Array

As shown in the figure above, the purple box is our original array.

Each element in the purple box array is a new array (the red box).

Knowledge Points:

  • Definition of a two-dimensional array
  • Initialization of a two-dimensional array
  • Traversing a two-dimensional array
  • Use of multidimensional arrays

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("`Go`")) -.-> go/BasicsGroup(["`Basics`"]) go(("`Go`")) -.-> go/FunctionsandControlFlowGroup(["`Functions and Control Flow`"]) go(("`Go`")) -.-> go/DataTypesandStructuresGroup(["`Data Types and Structures`"]) go/BasicsGroup -.-> go/variables("`Variables`") go/FunctionsandControlFlowGroup -.-> go/for("`For`") go/DataTypesandStructuresGroup -.-> go/slices("`Slices`") go/FunctionsandControlFlowGroup -.-> go/range("`Range`") go/FunctionsandControlFlowGroup -.-> go/functions("`Functions`") subgraph Lab Skills go/variables -.-> lab-149076{{"`Mastering Multidimensional Arrays in Go`"}} go/for -.-> lab-149076{{"`Mastering Multidimensional Arrays in Go`"}} go/slices -.-> lab-149076{{"`Mastering Multidimensional Arrays in Go`"}} go/range -.-> lab-149076{{"`Mastering Multidimensional Arrays in Go`"}} go/functions -.-> lab-149076{{"`Mastering Multidimensional Arrays in Go`"}} end

Definition of a Two-Dimensional Array

General Definition

Do you remember how we define a regular array?

var variableName [elementCount]variableType

So how do we define a two-dimensional array using this most naive method?

var variableName [elementCount][elementCount]variableType

The only difference is that we add another [elementCount] before the original [elementCount] to form the format [elementCount][elementCount].

For example, if we want to define a two-dimensional array named a with a capacity of 10*10 of type int, we can use the following syntax:

var a [10][10]int

Short Definition

Just like the short variable declaration, we can use a short definition method to declare arrays, even multidimensional arrays.

We can use := to declare an array, including multidimensional arrays.

For example:

a := [10][10]int{}

This way we define an integer two-dimensional array of size 10*10.

Initialization of a Two-Dimensional Array

Similar to one-dimensional arrays, we can initialize a two-dimensional array in the following ways:

  • Initialization list
  • Inferred length initialization
  • Specified index value initialization

Do you remember how to use these methods?

We have learned how to use these methods in one-dimensional arrays in the previous section. If you forget, it's okay.

The following section will review these three initialization methods and extend them to two-dimensional arrays.

Initialization of a Two-Dimensional Array Using an Initialization List

Let's continue using the array.go file created in the previous section. If you haven't saved your work, you can create the file as follows:

touch ~/project/array.go

Write the following code in array.go:

package main

import "fmt"

func main() {
    // Automatically initialized to 0
    var simpleArray [3][3]int
    // Initialize using specified initial values, use default values for the missing elements
    var numArray = [3][3]int{{1, 2, 3}, {2, 3, 4}}
    // Initialize using specified initial values
    var cityArray = [2][2]string{{"Hangzhou", "Chengdu"}, {"Beijing", "Chongqing"}}
    fmt.Println(simpleArray) // [[0 0 0] [0 0 0] [0 0 0]]
    fmt.Println(numArray)    // [[1 2 3] [2 3 4] [0 0 0]]
    fmt.Println(cityArray)   // [[Hangzhou Chengdu] [Beijing Chongqing]]
}

The above code demonstrates three ways to initialize a two-dimensional array using an initialization list.

The output is as follows:

[[0 0 0] [0 0 0] [0 0 0]]
[[1 2 3] [2 3 4] [0 0 0]]
[[Hangzhou Chengdu] [Beijing Chongqing]]

You can modify the values and review the initialization methods for one-dimensional arrays.

Initialization of a Two-Dimensional Array with Inferred Length

In a two-dimensional array, we can use the inferred length method to initialize it, just as we did with one-dimensional arrays.

Write the following code in array.go:

package main

import "fmt"

func main() {
    // Automatically initialized to 0
    var simpleArray [3][3]int
    // Initialize using specified initial values, use default values for the missing elements
    var numArray = [...][]int{{1, 2, 3, 3}, {2, 3, 4, 3}, {0}}
    // Initialize using specified initial values
    var cityArray = [...][2]string{{"Hangzhou", "Chengdu"}, {"Beijing", "Chongqing"}}
    fmt.Println(simpleArray) // [[0 0 0] [0 0 0] [0 0 0]]
    fmt.Println(numArray)    // [[1 2 3 3] [2 3 4 3] [0]]
    fmt.Println(cityArray)   // [[Hangzhou Chengdu] [Beijing Chongqing]]
}

The above code demonstrates using the inferred length to initialize a two-dimensional array.

The output is the same as the initialization list method.

However, unlike one-dimensional arrays, in the inferred length initialization of a two-dimensional array, the ... symbol can only exist in the first square brackets.

For example:

var numArray = [...][]int{{1, 2, 3, 3}, {2, 3, 4, 3}}

This code is valid, but the following two variations are incorrect:

var numArray = [][...]int{{1, 2, 3, 3}, {2, 3, 4, 3}}
var numArray = [...][...]int{{1, 2, 3, 3}, {2, 3, 4, 3}}

In addition, let's compare numArray and cityArray.

We can see that in cityArray, we specify the second parameter of the two-dimensional array's size, as shown below:

var cityArray = [...][2]string{{"Hangzhou", "Chengdu"}, {"Beijing", "Chongqing"}}

This means that we specify the size of each sub-array as 2 during initialization.

If the given values are not enough during initialization, the default values of the data type will be used to fill in the missing elements.

If the number of given values exceeds the specified size, an error will occur.

Initialization of a Two-Dimensional Array with Specified Index Values

Similar to one-dimensional arrays, we can also use the specified index values for initialization in a two-dimensional array. The process is similar.

Write the following code in array.go:

package main

import "fmt"

func main() {
    a := [...][]int{1: {1, 2, 3}, 3: {4, 7, 9}}
    fmt.Println(a)                  // [[] [1 2 3] [] [4 7 9]]
    fmt.Printf("Type of array a: %T\n", a) // Type of array a: [4][]int
}

The output is:

[[] [1 2 3] [] [4 7 9]]
Type of array a: [4][]int

The above code defines the array a as a two-dimensional array with an indeterminate length. We assign the value [1 2 3] to the array at index 1 and the value [4 7 9] to the array at index 3.

In the case of automatically inferred length, the type of array a is [4][]int.

Traversing a Two-Dimensional Array

How do we traverse a two-dimensional array?

When we learned about one-dimensional arrays, we used two methods for traversing arrays: using the range keyword and using index numbers.

Now let's apply these two methods to traverse a two-dimensional array.

Write the following code in array.go:

package main

import "fmt"

func main() {
    a := [...][]int{{123, 321, 222}, {404, 501, 503}, {857, 419, 857}}
    // Method 1: using the range keyword
    fmt.Println("Traversing the Two-Dimensional Array Using the range Keyword")
    for index, value := range a {
        for i, j := range value {
            fmt.Println(index, i, j)
        }
    }
    // Method 2: using index numbers
    fmt.Println("\nTraversing the Two-Dimensional Array Using Index Numbers")
    for i := 0; i < len(a); i++ {
        for j := 0; j < len(a[i]); j++ {
            fmt.Println(i, j, a[i][j])
        }
    }
}

The above code demonstrates two ways to traverse a two-dimensional array.

The output is:

Traversing the Two-Dimensional Array Using the range Keyword
0 0 123
0 1 321
0 2 222
1 0 404
1 1 501
1 2 503
2 0 857
2 1 419
2 2 857

Traversing the Two-Dimensional Array Using Index Numbers
0 0 123
0 1 321
0 2 222
1 0 404
1 1 501
1 2 503
2 0 857
2 1 419
2 2 857

Although both methods generate the same results, they are fundamentally different. These differences will be particularly evident in our actual use of arrays.

Practical Uses of Arrays

In the previous section, we mentioned that the two methods of array traversal are fundamentally different.

Let's use a small example to explain this.

Write the following code in array.go:

package main

import "fmt"

func main() {
    a := [...][]int{{123, 321, 222}, {404, 501, 503}, {857, 419, 857}}
    // Method 1: using the range keyword
    fmt.Println("Traversing the Two-Dimensional Array Using the range Keyword")
    for _, value := range a {
        for _, j := range value {
            fmt.Println(j)
            j = 0
        }
    }
    fmt.Println(a)
    // Method 2: using index numbers
    fmt.Println("\nTraversing the Two-Dimensional Array Using Index Numbers")
    for i := 0; i < len(a); i++ {
        for j := 0; j < len(a[i]); j++ {
            fmt.Println(a[i][j])
            a[i][j] = 0
        }
    }
    fmt.Println(a)
}

The above code demonstrates using the two different methods to set all values in the two-dimensional array to 0.

The program output is:

Traversing the Two-Dimensional Array Using the range Keyword
123
321
222
404
501
503
857
419
857
[[123 321 222] [404 501 503] [857 419 857]]

Traversing the Two-Dimensional Array Using Index Numbers
123
321
222
404
501
503
857
419
857
[[0 0 0] [0 0 0] [0 0 0]]

We find that when using the range keyword to traverse the array, modifying its value has no effect.

However, after using index numbers to traverse the array, modifying its value is effective. This is because when we use the range keyword to traverse the array, j is actually just a copy of the array's value. Modifying the value of the copy does not affect the original array a.

However, modifying the value of the original array is valid when using index numbers to traverse the array.

Upscaling a Two-Dimensional Array

Sometimes, we need to use a three-dimensional array or even a four-dimensional array.

Expanding to higher-dimensional arrays is not much different from expanding a one-dimensional array to a two-dimensional array.

Let's take a simple example:

package main

import "fmt"

func main() {
    a := [2][2][2]int{}
    for i := 0; i < 2; i++ {
        for j := 0; j < 2; j++ {
            for k := 0; k < 2; k++ {
                a[i][j][k] = 1
            }
        }
    }
    fmt.Println(a)
}

The above code demonstrates how to define and use a three-dimensional array. The process is the same for four-dimensional or higher-dimensional arrays.

However, higher-dimensional arrays are not commonly used. So understanding the concept is sufficient.

Summary

In this lab, we have learned the following:

  • Two methods for defining a two-dimensional array
  • Three methods for initializing a two-dimensional array
  • Two methods for traversing a two-dimensional array
  • The difference between the two traversal methods in actual use
  • An overview of using multidimensional arrays

In the next section, we will introduce slices, which are not only a feature of the Go language, but also an advanced topic in arrays.

Other Go Tutorials you may like