首页 > 编程笔记

Go语言数组详解

数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由 0 或多个元素组成。由于数组的长度是固定的,在开发中缺乏一定的灵活性,因此在 Go 语言中很少使用数组。

数组的定义和使用

Go 语言的数组定义语法如下:
// 定义数组
var name [number]type
语法说明如下:
数组的每个元素可以通过索引下标来访问,索引下标的范围是从 0 开始计算的,具体示例如下:
package main

import "fmt"

func main() {
    // 定义长度为2的数组
    var s [2]int
    // 输出数组元素
    for i := 0; i < len(s); i++ {
         fmt.Printf("数组第%v个元素是:%v\n", i+1, s[i])
    }
    // 修改数组的元素值
    s[0] = 100
    // 输出数组元素
    for i := 0; i < len(s); i++ {
         fmt.Printf("数组第%v个元素是:%v\n", i+1, s[i])
    }
}
上述代码运行结果为:

数组第1个元素是:0
数组第2个元素是:0
数组第1个元素是:100
数组第2个元素是:0

从运行结果看到,我们定义长度为 3 的数组,数组的每个元素的默认值为 0,这是 Go 语言自动分配的,如果数组定义为字符串类型,那么默认值为空字符串。

数组初始化定义

由于数组在定义的时候,Go 语言自动为数组元素设置默认值,每次修改数组元素都要通过索引下标,这样会为开发过程带来不便,因此 Go 语言在定义数组的时候,可以为每个元素设置初始化数值,其语法格式如下:
// 定义并初始化
var name = [number]type{v1, v2, v3}
// 根据初始化值设置数组长度
var name = [...]type{v1, v2, v3}
定义数组的时候,只需在数组的数据类型后面加上中括号“{}”,并在中括号里面设置元素的数值即可。根据上述语法格式,通过应用示例加以说明,代码如下:
package main

import "fmt"

func main() {
    // 定义长度为2的数组并设置每个元素值
    var s = [2]int{100, 200}
    // 输出数组元素
    for i := 0; i < len(s); i++ {
         fmt.Printf("数组s第%v个元素是:%v\n", i+1, s[i])
    }

    // 定义数组并设置每个元素值,数值长度根据元素个数自动设置
    var ss = [...]int{300, 400}
    // 输出数组元素
    for i := 0; i < len(ss); i++ {
         fmt.Printf("数组ss第%v个元素是:%v\n", i+1, ss[i])
    }

    // 定义数组并设置第1个和第4个元素值
    var sss = [...]int{0: 300, 3: 500}
    // 输出数组元素
    for i := 0; i < len(sss); i++ {
         fmt.Printf("数组sss第%v个元素是:%v\n", i+1, sss[i])
    }
}
上述代码中,分别演示了数组定义并初始化的 3 种方式,说明如下:
最后在 GoLand 中运行上述代码,运行结果为:

数组s第1个元素是:100 
数组s第2个元素是:200 
数组ss第1个元素是:300 
数组ss第2个元素是:400 
数组sss第1个元素是:300 
数组sss第2个元素是:0 
数组sss第3个元素是:0 
数组sss第4个元素是:500

GO多维数组

多维数组是在一个数组中嵌套了多个数组,数组之间是层层嵌套的,形成递进关系,语法定义如下:
// 定义长度固定的多维数组
var name [number1][number2]...[number3]type
语法说明如下:
二维数组和三维数组是开发中最常用的多维数组,二维数组主要实现表格类功能,如数据排列、汇总分析等;三维数组可以在二维数组的基础上再进行分类。下面分别通过两个应用示例说明二维数组和三维数组的定义与使用。
package main

import "fmt"

func main() {
    var result int = 0
    // 定义3行2列长度的二维数组
    var s [3][2]int
    // 为二维数组赋值
    s = [3][2]int{{10, 20}, {30, 40}, {50, 60}}
    for i := 0; i < len(s); i++ {
         // 循环每一行数据
         for k := 0; k < len(s[i]); k++ {
              // 循环每一列数据
              result = result + s[i][k]
              fmt.Printf("当前元素值为:%v\n", s[i][k])
         }
    }
    fmt.Printf("二维数组的总行数为:%v\n", len(s))
    fmt.Printf("二维数组的总列数为:%v\n", len(s[0]))
    fmt.Printf("二维数组的总值为:%v\n", result)
}
上述代码中定义了 3 行 2 列的二维数组,并为数组设置了初始值,我们将二维数组以表格形式展示,如下图所示:


图 1

如果要遍历二维数组的所有元素,需要使用循环嵌套,第一层循环是遍历数组的行数,第二层循环是遍历数组的列数。总的来说,遍历二维数组的元素必须遵守从上到下(先遍历行数),再从左到右(后遍历列数)的规则。

最后运行上述代码,运行结果为:

当前元素值为:10 
当前元素值为:20 
当前元素值为:30 
当前元素值为:40 
当前元素值为:50 
当前元素值为:60 
二维数组的总行数为:3 
二维数组的总列数为:2 
二维数组的总值为:210


下一步使用三维数组计算两个空间坐标点的距离,现有坐标点 A 为(x1, y1, z1),坐标点 B 为(x2, y2, z2),AB 两点距离的计算公式为:


实现代码如下:
package main

import (
    "fmt"
    "math"
)

func main() {
    // 定义2*1*3长度的三维数组
    var point [2][1][3]int
    point = [2][1][3]int{{{3, 5, 7}}, {{5, 3, 2}}}
    // 获取坐标点
    pointA := point[0][0]
    pointB := point[1][0]
    fmt.Printf("坐标点A:%v\n", pointA)
    fmt.Printf("坐标点B:%v\n", pointB)
    // 计算两个坐标点的距离
    // 计算两个坐标的x坐标之差的平方
    x := (pointA[0] - pointB[0]) * (pointA[0] - pointB[0])
    // 计算两个坐标的y坐标之差的平方
    y := (pointA[1] - pointB[1]) * (pointA[1] - pointB[1])
    // 计算两个坐标的z坐标之差的平方
    z := (pointA[2] - pointB[2]) * (pointA[2] - pointB[2])
    result := math.Sqrt(float64(x+y+z))
    fmt.Printf("两坐标点距离为:%v\n", result)
}
从上述代码看到,空间坐标点 x、y、z 都存放在三维数组的最内层,前两层主要限制数据格式,比如 var point [2][1][3]int 的数值 2 代表两个坐标点,数值 1 代表每个坐标点只能设置一个数组,数值 3 代表坐标点 x、y、z 的坐标值。

二维数组也能记录空间坐标点,并且在使用上更加便捷,如果空间坐标点较多,三维数组就能对有规律性的坐标点进行归类。比如 var point [2][5][3]int 的数值 5 能记录 5 个同一规律的坐标点。

最后运行上述代码,运行结果为:

坐标点A:[3 5 7] 
坐标点B:[5 3 2] 
两坐标点距离为:5.744562646538029

推荐阅读