Go 语言多维数组
多维数组是数组的数组,可以把它想象成一个数据表格或矩阵,其中每个元素都可以通过多个索引来访问。
Go 语言中的多维数组可用于处理表格数据、矩阵运算或游戏棋盘等结构化的信息。
基本概念
- 一维数组:像一条直线上的点,只需要一个坐标(索引)就能找到特定元素
- 二维数组:像一个表格,需要行和列两个坐标
- 三维数组:像一个立方体,需要长、宽、高三个坐标
- 更高维度:理论上可以有多维,但实际编程中二维和三维最常用
可以从我们平时的停车位来比拟:
- 一维数组 = 一排停车位(只需要车位编号)
- 二维数组 = 多层停车场(需要楼层和车位编号)
- 三维数组 = 多个多层停车场(需要停车场编号、楼层和车位编号)
Go 语言支持多维数组,以下为常用的多维数组声明方式:
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
声明与初始化:
// 声明一个二维数组 var 数组名 [行数][列数]元素类型 // 声明并初始化 var 数组名 [行数][列数]元素类型 = [行数][列数]元素类型{初始化值}以下实例声明了三维的整型数组:
var threedim [5][10][4]int
二维数组
二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:
var arrayName [ x ][ y ] variable_type
variable_type 为 Go 语言的数据类型,arrayName 为数组名,二维数组可认为是一个表格,x 为行,y 为列,下图演示了一个二维数组 a 为三行四列:

二维数组中的元素可通过 a[ i ][ j ] 来访问。
实例
package main
import "fmt"
func main() {
// Step 1: 创建数组
values := [][]int{}
// Step 2: 使用 append() 函数向空的二维数组添加两行一维数组
row1 := []int{1, 2, 3}
row2 := []int{4, 5, 6}
values = append(values, row1)
values = append(values, row2)
// Step 3: 显示两行数据
fmt.Println("Row 1")
fmt.Println(values[0])
fmt.Println("Row 2")
fmt.Println(values[1])
// Step 4: 访问第一个元素
fmt.Println("第一个元素为:")
fmt.Println(values[0][0])
}
import "fmt"
func main() {
// Step 1: 创建数组
values := [][]int{}
// Step 2: 使用 append() 函数向空的二维数组添加两行一维数组
row1 := []int{1, 2, 3}
row2 := []int{4, 5, 6}
values = append(values, row1)
values = append(values, row2)
// Step 3: 显示两行数据
fmt.Println("Row 1")
fmt.Println(values[0])
fmt.Println("Row 2")
fmt.Println(values[1])
// Step 4: 访问第一个元素
fmt.Println("第一个元素为:")
fmt.Println(values[0][0])
}
以上实例运行输出结果为:
Row 1 [1 2 3] Row 2 [4 5 6] 第一个元素为: 1
初始化二维数组
多维数组可通过大括号来初始值。以下实例为一个 3 行 4 列的二维数组:
a := [3][4]int{
{0, 1, 2, 3} , /* 第一行索引为 0 */
{4, 5, 6, 7} , /* 第二行索引为 1 */
{8, 9, 10, 11}, /* 第三行索引为 2 */
}
注意:以上代码中倒数第二行的 } 必须要有逗号,因为最后一行的 } 不能单独一行,也可以写成这样:
a := [3][4]int{
{0, 1, 2, 3} , /* 第一行索引为 0 */
{4, 5, 6, 7} , /* 第二行索引为 1 */
{8, 9, 10, 11}} /* 第三行索引为 2 */
以下实例初始化一个 2 行 2 列 的二维数组:
实例
package main
import "fmt"
func main() {
// 创建二维数组
sites := [2][2]string{}
// 向二维数组添加元素
sites[0][0] = "Google"
sites[0][1] = "Runoob"
sites[1][0] = "Taobao"
sites[1][1] = "Weibo"
// 显示结果
fmt.Println(sites)
}
import "fmt"
func main() {
// 创建二维数组
sites := [2][2]string{}
// 向二维数组添加元素
sites[0][0] = "Google"
sites[0][1] = "Runoob"
sites[1][0] = "Taobao"
sites[1][1] = "Weibo"
// 显示结果
fmt.Println(sites)
}
以上实例运行输出结果为:
[[Google Runoob] [Taobao Weibo]]
访问二维数组
二维数组通过指定坐标来访问。如数组中的行索引与列索引,例如:
val := a[2][3] 或 var value int = a[2][3]
以上实例访问了二维数组 val 第三行的第四个元素。
二维数组可以使用循环嵌套来输出元素:
实例
package main
import "fmt"
func main() {
/* 数组 - 5 行 2 列*/
var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}
var i, j int
/* 输出数组元素 */
for i = 0; i < 5; i++ {
for j = 0; j < 2; j++ {
fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )
}
}
}
import "fmt"
func main() {
/* 数组 - 5 行 2 列*/
var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}
var i, j int
/* 输出数组元素 */
for i = 0; i < 5; i++ {
for j = 0; j < 2; j++ {
fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )
}
}
}
以上实例运行输出结果为:
a[0][0] = 0 a[0][1] = 0 a[1][0] = 1 a[1][1] = 2 a[2][0] = 2 a[2][1] = 4 a[3][0] = 3 a[3][1] = 6 a[4][0] = 4 a[4][1] = 8
以下实例创建各个维度元素数量不一致的多维数组:
实例
package main
import "fmt"
func main() {
// 创建空的二维数组
animals := [][]string{}
// 创建三一维数组,各数组长度不同
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// 使用 append() 函数将一维数组添加到二维数组中
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
// 循环输出
for i := range animals {
fmt.Printf("Row: %v\n", i)
fmt.Println(animals[i])
}
}
import "fmt"
func main() {
// 创建空的二维数组
animals := [][]string{}
// 创建三一维数组,各数组长度不同
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// 使用 append() 函数将一维数组添加到二维数组中
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
// 循环输出
for i := range animals {
fmt.Printf("Row: %v\n", i)
fmt.Println(animals[i])
}
}
以上实例运行输出结果为:
Row: 0 [fish shark eel] Row: 1 [bird] Row: 2 [lizard salamander]
访问和修改数组元素
访问元素
实例
package main
import "fmt"
func main() {
// 创建一个3x3的矩阵
matrix := [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
// 访问单个元素
fmt.Println("第一行第二列:", matrix[0][1]) // 输出: 2
fmt.Println("第三行第三列:", matrix[2][2]) // 输出: 9
// 访问整行
fmt.Println("第二行:", matrix[1]) // 输出: [4 5 6]
// 遍历所有元素
fmt.Println("\n遍历所有元素:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j])
}
}
}
import "fmt"
func main() {
// 创建一个3x3的矩阵
matrix := [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
// 访问单个元素
fmt.Println("第一行第二列:", matrix[0][1]) // 输出: 2
fmt.Println("第三行第三列:", matrix[2][2]) // 输出: 9
// 访问整行
fmt.Println("第二行:", matrix[1]) // 输出: [4 5 6]
// 遍历所有元素
fmt.Println("\n遍历所有元素:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j])
}
}
}
修改元素
实例
package main
import "fmt"
func main() {
// 创建一个2x2的零值矩阵
var grid [2][2]int
fmt.Println("修改前的矩阵:", grid)
// 修改特定位置的元素
grid[0][0] = 10
grid[0][1] = 20
grid[1][0] = 30
grid[1][1] = 40
fmt.Println("修改后的矩阵:", grid)
// 批量修改一行
grid[0] = [2]int{100, 200}
fmt.Println("修改第一行后:", grid)
}
import "fmt"
func main() {
// 创建一个2x2的零值矩阵
var grid [2][2]int
fmt.Println("修改前的矩阵:", grid)
// 修改特定位置的元素
grid[0][0] = 10
grid[0][1] = 20
grid[1][0] = 30
grid[1][1] = 40
fmt.Println("修改后的矩阵:", grid)
// 批量修改一行
grid[0] = [2]int{100, 200}
fmt.Println("修改第一行后:", grid)
}
三维及更高维数组
三维数组示例
实例
package main
import "fmt"
func main() {
// 声明一个2x3x4的三维数组
// 可以理解为:2个平面,每个平面有3行4列
var cube [2][3][4]int
// 初始化三维数组
cube = [2][3][4]int{
{ // 第一个平面
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
},
{ // 第二个平面
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24},
},
}
// 访问三维数组元素
fmt.Println("cube[0][1][2] =", cube[0][1][2]) // 输出: 7
fmt.Println("cube[1][2][3] =", cube[1][2][3]) // 输出: 24
// 遍历三维数组
fmt.Println("\n三维数组内容:")
for i := 0; i < 2; i++ {
fmt.Printf("平面 %d:\n", i)
for j := 0; j < 3; j++ {
for k := 0; k < 4; k++ {
fmt.Printf("%3d ", cube[i][j][k])
}
fmt.Println()
}
fmt.Println()
}
}
import "fmt"
func main() {
// 声明一个2x3x4的三维数组
// 可以理解为:2个平面,每个平面有3行4列
var cube [2][3][4]int
// 初始化三维数组
cube = [2][3][4]int{
{ // 第一个平面
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
},
{ // 第二个平面
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24},
},
}
// 访问三维数组元素
fmt.Println("cube[0][1][2] =", cube[0][1][2]) // 输出: 7
fmt.Println("cube[1][2][3] =", cube[1][2][3]) // 输出: 24
// 遍历三维数组
fmt.Println("\n三维数组内容:")
for i := 0; i < 2; i++ {
fmt.Printf("平面 %d:\n", i)
for j := 0; j < 3; j++ {
for k := 0; k < 4; k++ {
fmt.Printf("%3d ", cube[i][j][k])
}
fmt.Println()
}
fmt.Println()
}
}
参见下图:

多维数组的常用操作
1. 使用 range 遍历
实例
package main
import "fmt"
func main() {
// 创建一个二维数组
scores := [3][4]int{
{85, 90, 78, 92},
{88, 76, 95, 89},
{92, 85, 88, 90},
}
fmt.Println("学生成绩表:")
// 使用 range 遍历二维数组
for i, row := range scores {
fmt.Printf("学生 %d 的成绩: ", i+1)
for j, score := range row {
fmt.Printf("%d ", score)
// 如果需要索引和值都使用
_ = j // 避免未使用变量警告
}
fmt.Println()
}
// 只关心值,不关心索引
total := 0
count := 0
for _, row := range scores {
for _, score := range row {
total += score
count++
}
}
fmt.Printf("\n平均分: %.2f\n", float64(total)/float64(count))
}
import "fmt"
func main() {
// 创建一个二维数组
scores := [3][4]int{
{85, 90, 78, 92},
{88, 76, 95, 89},
{92, 85, 88, 90},
}
fmt.Println("学生成绩表:")
// 使用 range 遍历二维数组
for i, row := range scores {
fmt.Printf("学生 %d 的成绩: ", i+1)
for j, score := range row {
fmt.Printf("%d ", score)
// 如果需要索引和值都使用
_ = j // 避免未使用变量警告
}
fmt.Println()
}
// 只关心值,不关心索引
total := 0
count := 0
for _, row := range scores {
for _, score := range row {
total += score
count++
}
}
fmt.Printf("\n平均分: %.2f\n", float64(total)/float64(count))
}
2. 数组长度获取
实例
package main
import "fmt"
func main() {
// 创建一个不规则的多维数组
jagged := [3][3]int{
{1, 2, 3},
{4, 5},
{6, 7, 8, 9}, // 注意:这里会编译错误,因为每行必须长度一致
}
// 正确的示例:获取数组维度
matrix := [4][5]int{}
// 获取行数
rows := len(matrix)
fmt.Println("行数:", rows) // 输出: 4
// 获取第一行的列数(所有行长度相同)
cols := len(matrix[0])
fmt.Println("列数:", cols) // 输出: 5
// 获取总元素数
totalElements := rows * cols
fmt.Println("总元素数:", totalElements) // 输出: 20
}
import "fmt"
func main() {
// 创建一个不规则的多维数组
jagged := [3][3]int{
{1, 2, 3},
{4, 5},
{6, 7, 8, 9}, // 注意:这里会编译错误,因为每行必须长度一致
}
// 正确的示例:获取数组维度
matrix := [4][5]int{}
// 获取行数
rows := len(matrix)
fmt.Println("行数:", rows) // 输出: 4
// 获取第一行的列数(所有行长度相同)
cols := len(matrix[0])
fmt.Println("列数:", cols) // 输出: 5
// 获取总元素数
totalElements := rows * cols
fmt.Println("总元素数:", totalElements) // 输出: 20
}
3. 数组比较
实例
package main
import "fmt"
func main() {
// 创建两个相同的二维数组
a := [2][2]int{{1, 2}, {3, 4}}
b := [2][2]int{{1, 2}, {3, 4}}
c := [2][2]int{{1, 2}, {3, 5}}
// 数组可以直接比较(只有当维度完全相同时)
fmt.Println("a == b:", a == b) // 输出: true
fmt.Println("a == c:", a == c) // 输出: false
// 注意:不同维度的数组不能比较
// d := [2][3]int{{1, 2, 3}, {4, 5, 6}}
// fmt.Println(a == d) // 编译错误:类型不匹配
}
import "fmt"
func main() {
// 创建两个相同的二维数组
a := [2][2]int{{1, 2}, {3, 4}}
b := [2][2]int{{1, 2}, {3, 4}}
c := [2][2]int{{1, 2}, {3, 5}}
// 数组可以直接比较(只有当维度完全相同时)
fmt.Println("a == b:", a == b) // 输出: true
fmt.Println("a == c:", a == c) // 输出: false
// 注意:不同维度的数组不能比较
// d := [2][3]int{{1, 2, 3}, {4, 5, 6}}
// fmt.Println(a == d) // 编译错误:类型不匹配
}
实际应用场景
场景1:游戏棋盘(井字棋)
实例
package main
import "fmt"
func main() {
// 初始化一个3x3的井字棋棋盘
var board [3][3]string
// 初始化为空
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
board[i][j] = " "
}
}
// 模拟下棋
board[0][0] = "X"
board[1][1] = "O"
board[2][2] = "X"
// 打印棋盘
fmt.Println("井字棋棋盘:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf(" %s ", board[i][j])
if j < 2 {
fmt.Printf("|")
}
}
fmt.Println()
if i < 2 {
fmt.Println("---+---+---")
}
}
}
import "fmt"
func main() {
// 初始化一个3x3的井字棋棋盘
var board [3][3]string
// 初始化为空
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
board[i][j] = " "
}
}
// 模拟下棋
board[0][0] = "X"
board[1][1] = "O"
board[2][2] = "X"
// 打印棋盘
fmt.Println("井字棋棋盘:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf(" %s ", board[i][j])
if j < 2 {
fmt.Printf("|")
}
}
fmt.Println()
if i < 2 {
fmt.Println("---+---+---")
}
}
}
场景2:学生成绩管理系统
实例
package main
import "fmt"
func main() {
// 定义:3个学生,每个学生有4门课程
var grades [3][4]float64
// 输入学生成绩
grades = [3][4]float64{
{85.5, 90.0, 78.5, 92.0}, // 学生1的成绩
{88.0, 76.5, 95.0, 89.5}, // 学生2的成绩
{92.5, 85.0, 88.5, 90.0}, // 学生3的成绩
}
// 计算每个学生的平均分
fmt.Println("学生成绩统计:")
for i, studentGrades := range grades {
sum := 0.0
for _, grade := range studentGrades {
sum += grade
}
average := sum / float64(len(studentGrades))
fmt.Printf("学生 %d: 平均分 = %.2f\n", i+1, average)
}
// 计算每门课程的平均分
fmt.Println("\n课程平均分:")
for j := 0; j < 4; j++ {
sum := 0.0
for i := 0; i < 3; i++ {
sum += grades[i][j]
}
average := sum / 3.0
fmt.Printf("课程 %d: 平均分 = %.2f\n", j+1, average)
}
}
import "fmt"
func main() {
// 定义:3个学生,每个学生有4门课程
var grades [3][4]float64
// 输入学生成绩
grades = [3][4]float64{
{85.5, 90.0, 78.5, 92.0}, // 学生1的成绩
{88.0, 76.5, 95.0, 89.5}, // 学生2的成绩
{92.5, 85.0, 88.5, 90.0}, // 学生3的成绩
}
// 计算每个学生的平均分
fmt.Println("学生成绩统计:")
for i, studentGrades := range grades {
sum := 0.0
for _, grade := range studentGrades {
sum += grade
}
average := sum / float64(len(studentGrades))
fmt.Printf("学生 %d: 平均分 = %.2f\n", i+1, average)
}
// 计算每门课程的平均分
fmt.Println("\n课程平均分:")
for j := 0; j < 4; j++ {
sum := 0.0
for i := 0; i < 3; i++ {
sum += grades[i][j]
}
average := sum / 3.0
fmt.Printf("课程 %d: 平均分 = %.2f\n", j+1, average)
}
}
场景3:图像像素处理
实例
package main
import "fmt"
func main() {
// 模拟一个简单的3x3灰度图像
// 每个像素值范围:0(黑色) ~ 255(白色)
var image [3][3]int
// 初始化图像(一个简单的渐变)
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
image[i][j] = (i + j) * 50
}
}
// 显示原始图像
fmt.Println("原始图像:")
displayImage(image)
// 图像处理:增加亮度
fmt.Println("\n增加亮度后的图像:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
// 增加亮度,但不超过255
newValue := image[i][j] + 50
if newValue > 255 {
newValue = 255
}
image[i][j] = newValue
}
}
displayImage(image)
}
func displayImage(img [3][3]int) {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%3d ", img[i][j])
}
fmt.Println()
}
}
import "fmt"
func main() {
// 模拟一个简单的3x3灰度图像
// 每个像素值范围:0(黑色) ~ 255(白色)
var image [3][3]int
// 初始化图像(一个简单的渐变)
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
image[i][j] = (i + j) * 50
}
}
// 显示原始图像
fmt.Println("原始图像:")
displayImage(image)
// 图像处理:增加亮度
fmt.Println("\n增加亮度后的图像:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
// 增加亮度,但不超过255
newValue := image[i][j] + 50
if newValue > 255 {
newValue = 255
}
image[i][j] = newValue
}
}
displayImage(image)
}
func displayImage(img [3][3]int) {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%3d ", img[i][j])
}
fmt.Println()
}
}
注意事项和最佳实践
1. 数组长度是类型的一部分
实例
package main
import "fmt"
func main() {
// 这两个是不同的类型!
var a [2][3]int
var b [3][2]int
// 以下代码会编译错误
// a = b // 错误:类型不匹配
fmt.Printf("a 的类型: %T\n", a) // [2][3]int
fmt.Printf("b 的类型: %T\n", b) // [3][2]int
}
import "fmt"
func main() {
// 这两个是不同的类型!
var a [2][3]int
var b [3][2]int
// 以下代码会编译错误
// a = b // 错误:类型不匹配
fmt.Printf("a 的类型: %T\n", a) // [2][3]int
fmt.Printf("b 的类型: %T\n", b) // [3][2]int
}
2. 值类型 vs 引用类型
实例
package main
import "fmt"
func main() {
// 数组是值类型
original := [2][2]int{{1, 2}, {3, 4}}
// 赋值会创建副本
copy := original
// 修改副本不会影响原始数组
copy[0][0] = 100
fmt.Println("原始数组:", original) // [[1 2] [3 4]]
fmt.Println("副本数组:", copy) // [[100 2] [3 4]]
// 如果需要引用语义,可以使用切片(后续文章会介绍)
}
import "fmt"
func main() {
// 数组是值类型
original := [2][2]int{{1, 2}, {3, 4}}
// 赋值会创建副本
copy := original
// 修改副本不会影响原始数组
copy[0][0] = 100
fmt.Println("原始数组:", original) // [[1 2] [3 4]]
fmt.Println("副本数组:", copy) // [[100 2] [3 4]]
// 如果需要引用语义,可以使用切片(后续文章会介绍)
}
3. 性能考虑
- 内存连续:多维数组在内存中是连续存储的,访问速度快
- 固定大小:数组长度在编译时确定,无法动态改变
- 适合场景:当数据大小已知且固定时,数组是最佳选择
常见问题解答
Q1: 多维数组和嵌套切片有什么区别?
| 特性 | 多维数组 | 嵌套切片 |
|---|---|---|
| 大小 | 固定,编译时确定 | 动态,运行时可变 |
| 内存 | 连续分配 | 可能不连续 |
| 性能 | 访问速度快 | 稍慢,有额外开销 |
| 使用场景 | 数据大小已知 | 数据大小可变 |
Q2: 如何创建不规则的二维数组?
Go 的数组要求每行长度相同。如果需要不规则结构,应该使用切片:
实例
// 使用切片创建不规则结构
irregular := [][]int{
{1, 2, 3},
{4, 5}, // 这行只有2个元素
{6, 7, 8, 9}, // 这行有4个元素
}
irregular := [][]int{
{1, 2, 3},
{4, 5}, // 这行只有2个元素
{6, 7, 8, 9}, // 这行有4个元素
}
Q3: 多维数组可以作为函数参数吗?
可以,但要注意数组是值类型,传递大数组会有性能开销:
实例
func processMatrix(matrix [3][3]int) [3][3]int {
// 处理矩阵...
matrix[0][0] = 100
return matrix
}
// 更好的方式是使用指针或切片
func processMatrixPtr(matrix *[3][3]int) {
matrix[0][0] = 100
}
// 处理矩阵...
matrix[0][0] = 100
return matrix
}
// 更好的方式是使用指针或切片
func processMatrixPtr(matrix *[3][3]int) {
matrix[0][0] = 100
}

Go 语言数组