Go Multi Dimensional Arrays
[Go Language Arrays](#)
Multi-dimensional arrays are arrays of arrays. You can think of them as a **data table** or **matrix**, where each element can be accessed via multiple indices.
In Go, multi-dimensional arrays can be used to handle structured information such as tabular data, matrix operations, or game boards.
### Basic Concepts
* **One-dimensional array**: Like points on a straight line, you only need one coordinate (index) to find a specific element.
* **Two-dimensional array**: Like a table, you need two coordinates: row and column.
* **Three-dimensional array**: Like a cube, you need three coordinates: length, width, and height.
* **Higher dimensions**: Theoretically, there can be many dimensions, but in practice, two and three dimensions are most commonly used.
We can draw an analogy from our daily parking spaces:
* **One-dimensional array** = A row of parking spaces (only need the space number).
* **Two-dimensional array** = A multi-story parking garage (need floor and space number).
* **Three-dimensional array** = Multiple multi-story parking garages (need garage number, floor, and space number).
Go supports multi-dimensional arrays. The following are common ways to declare multi-dimensional arrays:
var variable_name ... variable_type
Declaration and Initialization:
// Declare a two-dimensional array
var arrayName elementType
// Declare and initialize
var arrayName elementType = elementType{initialization values}
The following example declares a three-dimensional integer array:
var threedim int
* * *
## Two-dimensional Arrays
A two-dimensional array is the simplest multi-dimensional array. A two-dimensional array is essentially composed of one-dimensional arrays. The definition of a two-dimensional array is as follows:
var arrayName variable_type
`variable_type` is the data type in Go, `arrayName` is the array name. A two-dimensional array can be considered a table, where `x` is the row and `y` is the column. The following diagram illustrates a two-dimensional array `a` with three rows and four columns:
!(#)
Elements in a two-dimensional array can be accessed via `a`.
## Example
package main
import "fmt"
func main() {
// Step 1: Create an array
values := [][]int{}
// Step 2: Use the append() function to add two one-dimensional arrays (rows) to the empty two-dimensional array
row1 := []int{1, 2, 3}
row2 := []int{4, 5, 6}
values = append(values, row1)
values = append(values, row2)
// Step 3: Display the two rows of data
fmt.Println("Row 1")
fmt.Println(values)
fmt.Println("Row 2")
fmt.Println(values)
// Step 4: Access the first element
fmt.Println("The first element is:")
fmt.Println(values)
}
The output of the above example is:
Row 1
Row 2
The first element is:
1
* * *
## Initializing Two-dimensional Arrays
Multi-dimensional arrays can be initialized using curly braces. The following example is a two-dimensional array with 3 rows and 4 columns:
a := int{
{0, 1, 2, 3}, /* Row index 0 */
{4, 5, 6, 7}, /* Row index 1 */
{8, 9, 10, 11}, /* Row index 2 */
}
> **Note:** In the code above, the second-to-last line's **}** must have a comma, because the last line's **}** cannot be on a line by itself. It can also be written as:
a := int{
{0, 1, 2, 3}, /* Row index 0 */
{4, 5, 6, 7}, /* Row index 1 */
{8, 9, 10, 11}} /* Row index 2 */
The following example initializes a two-dimensional array with 2 rows and 2 columns:
## Example
package main
import "fmt"
func main() {
// Create a two-dimensional array
sites := string{}
// Add elements to the two-dimensional array
sites = "Google"
sites = ""
sites = "Taobao"
sites = "Weibo"
// Display the result
fmt.Println(sites)
}
The output of the above example is:
[ ]
* * *
## Accessing Two-dimensional Arrays
A two-dimensional array is accessed by specifying coordinates, such as the row index and column index in the array. For example:
val := a
or
var value int = a
The above example accesses the fourth element of the third row in the two-dimensional array `val`.
Two-dimensional arrays can use nested loops to output elements:
## Example
package main
import "fmt"
func main() {
/* Array - 5 rows, 2 columns */
var a = int{{0, 0}, {1, 2}, {2, 4}, {3, 6}, {4, 8}}
var i, j int
/* Output array elements */
for i = 0; i < 5; i++ {
for j = 0; j < 2; j++ {
fmt.Printf("a[%d][%d] = %dn", i, j, a)
}
}
}
The output of the above example is:
a = 0
a = 0
a = 1
a = 2
a = 2
a = 4
a = 3
a = 6
a = 4
a = 8
The following example creates a multi-dimensional array where the number of elements in each dimension is not consistent:
## Example
package main
import "fmt"
func main() {
// Create an empty two-dimensional array
animals := [][]string{}
// Create three one-dimensional arrays, each of different length
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// Use the append() function to add the one-dimensional arrays to the two-dimensional array
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
// Loop and output
for i := range animals {
fmt.Printf("Row: %vn", i)
fmt.Println(animals)
}
}
The output of the above example is:
Row: 0
Row: 1
Row: 2
* * *
## Accessing and Modifying Array Elements
### Accessing Elements
## Example
package main
import "fmt"
func main() {
// Create a 3x3 matrix
matrix := int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
// Access a single element
fmt.Println("Row 1, Column 2:", matrix) // Output: 2
fmt.Println("Row 3, Column 3:", matrix) // Output: 9
// Access an entire row
fmt.Println("Row 2:", matrix) // Output:
// Traverse all elements
fmt.Println("nTraversing all elements:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("matrix[%d][%d] = %dn", i, j, matrix)
}
}
}
### Modifying Elements
## Example
package main
import "fmt"
func main() {
// Create a 2x2 zero-value matrix
var grid int
fmt.Println("Matrix before modification:", grid)
// Modify elements at specific positions
grid = 10
grid = 20
grid = 30
grid = 40
fmt.Println("Matrix after modification:", grid)
// Batch modify a row
grid = int{100, 200}
fmt.Println("After modifying the first row:", grid)
}
* * *
## Three-dimensional and Higher-dimensional Arrays
### Three-dimensional Array Example
## Example
package main
import "fmt"
func main() {
// Declare a 2x3x4 three-dimensional array
// Can be understood as: 2 planes, each plane has 3 rows and 4 columns
var cube int
// Initialize the three-dimensional array
cube = int{
{ // First plane
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
},
{ // Second plane
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24},
},
}
// Access three-dimensional array elements
fmt.Println("cube =", cube) // Output: 7
fmt.Println("cube =", cube) // Output: 24
// Traverse the three-dimensional array
fmt.Println("nThree-dimensional array content:")
for i := 0; i < 2; i++ {
fmt.Printf("Plane %d:n", i)
for j := 0; j < 3; j++ {
for k := 0; k < 4; k++ {
fmt.Printf("%3d ", cube)
}
fmt.Println()
}
fmt.Println()
}
}
**See the diagram below:**
!(#)
* * *
## Common Operations on Multi-dimensional Arrays
### 1. Traversal using `range`
## Example
package main
import "fmt"
func main() {
// Create a two-dimensional array
scores := int{
{85, 90, 78, 92},
{88, 76, 95, 89},
{92, 85, 88, 90},
}
fmt.Println("Student Grade Table:")
// Use range to traverse the two-dimensional array
for i, row := range scores {
fmt.Printf("Student %d's grades: ", i+1)
for j, score := range row {
fmt.Printf("%d ", score)
// If you need both index and value
_ = j // Avoid unused variable warning
}
fmt.Println()
}
// Only care about values, not indices
total := 0
count := 0
for _, row := range scores {
for _, score := range row {
total += score
count++
}
}
fmt.Printf("nAverage score: %.2fn", float64(total)/float64(count))
}
### 2. Getting Array Length
## Example
package main
import "fmt"
func main() {
// Create an irregular multi-dimensional array (Note: This is invalid in Go, as shown in the comment)
// jagged := int{
// {1, 2, 3},
// {4, 5}, // This row has only 2 elements
// {6, 7, 8, 9}, // This row has 4 elements. Note: This will cause a compile error because each row must have the same length.
// }
// Correct example: Get array dimensions
matrix := int{}
// Get the number of rows
rows := len(matrix)
fmt.Println("Rows:", rows) // Output: 4
// Get the number of columns in the first row (all rows have the same length)
cols := len(matrix)
fmt.Println("Columns:", cols) // Output: 5
// Get the total number of elements
totalElements := rows * cols
fmt.Println("Total elements:", totalElements) // Output: 20
}
### 3. Array Comparison
## Example
package main
import "fmt"
func main() {
// Create two identical two-dimensional arrays
a := int{{1, 2}, {3, 4}}
b := int{{1, 2}, {3, 4}}
c := int{{1, 2}, {3, 5}}
// Arrays can be compared directly (only when dimensions are exactly the same)
fmt.Println("a == b:", a == b) // Output: true
fmt.Println("a == c:", a == c) // Output: false
// Note: Arrays of different dimensions cannot be compared
// d := int{{1, 2, 3}, {4, 5, 6}}
// fmt.Println(a == d) // Compile error: type mismatch
}
* * *
## Practical Application Scenarios
### Scenario 1: Game Board (Tic-Tac-Toe)
## Example
package main
import "fmt"
func main() {
// Initialize a 3x3 Tic-Tac-Toe board
var board string
// Initialize to empty
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
board = " "
}
}
// Simulate moves
board = "X"
board = "O"
board = "X"
// Print the board
fmt.Println("Tic-Tac-Toe Board:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf(" %s ", board)
if j < 2 {
fmt.Printf("|")
}
}
fmt.Println()
if i < 2 {
fmt.Println("---+---+---")
}
}
}
### Scenario 2: Student Grade Management System
## Example
package main
import "fmt"
func main() {
// Define: 3 students, each with 4 courses
var grades float64
// Input student grades
grades = float64{
{85.5, 90.0, 78.5, 92.0}, // Student 1's grades
{88.0, 76.5, 95.0, 89.5}, // Student 2's grades
{92.5, 85.0, 88.5, 90.0}, // Student 3's grades
}
// Calculate the average grade for each student
fmt.Println("Student Grade Statistics:")
for i, studentGrades := range grades {
sum := 0.0
for _, grade := range studentGrades {
sum += grade
}
average := sum / float64(len(studentGrades))
fmt.Printf("Student %d: Average = %.2fn", i+1, average)
}
// Calculate the average grade for each course
fmt.Println("nCourse Averages:")
for j := 0; j < 4; j++ {
sum := 0.0
for i := 0; i < 3; i++ {
sum += grades
}
average := sum / 3.0
fmt.Printf("Course %d: Average = %.2fn", j+1, average)
}
}
### Scenario 3: Image Pixel Processing
## Example
package main
import "fmt"
func main() {
// Simulate a simple 3x3 grayscale image
// Each pixel value range: 0 (black) ~ 255 (white)
var image int
// Initialize the image (a simple gradient)
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
image = (i + j) * 50
}
}
// Display the original image
fmt.Println("Original Image:")
displayImage(image)
// Image processing: Increase brightness
fmt.Println("nImage after increasing brightness:")
for i := 0; i < 3; i++ {
for j := 0; j 255 {
newValue = 255
}
image = newValue
}
}
displayImage(image)
}
func displayImage(img int) {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%3d ", img)
}
fmt.Println()
}
}
* * *
## Notes and Best Practices
### 1. Array Length is Part of the Type
## Example
package main
import "fmt"
func main() {
// These two are different types!
var a int
var b int
// The following code will cause a compile error
// a = b // Error: type mismatch
fmt.Printf("Type of a: %Tn", a) // int
fmt.Printf("Type of b: %Tn", b) // int
}
### 2. Value Type vs Reference Type
## Example
package main
import "fmt"
func main() {
// Arrays are value types
original := int{{1, 2}, {3, 4}}
// Assignment creates a copy
copy := original
// Modifying the copy does not affect the original array
copy = 100
fmt.Println("Original array:", original) // [ ]
fmt.Println("Copy array:", copy) // [ ]
// If you need reference semantics, you can use slices (covered in a later article)
}
### 3. Performance Considerations
* **Contiguous Memory**: Multi-dimensional arrays are stored contiguously in memory, leading to fast access.
* **Fixed Size**: The array length is determined at compile time and cannot be changed dynamically.
* **Suitable Scenarios**: When the data size is known and fixed, arrays are the best choice.
* * *
## Frequently Asked Questions
### Q1: What is the difference between multi-dimensional arrays and nested slices?
| Feature | Multi-dimensional Arrays | Nested Slices |
| --- | --- | --- |
| Size | Fixed, determined at compile time | Dynamic, variable at runtime |
| Memory | Contiguous allocation | May not be contiguous |
| Performance | Fast access | Slightly slower, with overhead |
| Use Case | Data size is known | Data size is variable |
### Q2: How to create an irregular two-dimensional array?
Go arrays require each row to have the same length. If you need an irregular structure, you should use slices:
## Example
// Use slices to create an irregular structure
irregular := [][]int{
{1, 2, 3},
{4, 5}, // This row has only 2 elements
{6, 7, 8, 9}, // This row has 4 elements
}
### Q3: Can multi-dimensional arrays be used as function parameters?
Yes, but be aware that arrays are value types, and passing large arrays can have performance overhead:
## Example
func processMatrix(matrix int) int {
// Process the matrix...
matrix = 100
return matrix
}
// A better way is to use pointers or slices
func processMatrixPtr(matrix *int) {
matrix = 100
}
[Go Language Arrays](#)
YouTip