Go语言实践[回顾]教程18--详解Go语言复合数据类型之数组 [...]

  数组,顾名思义就是数据的组合,但必须是相同类型数据。Go 语言的数组是一个由固定长度(元素个数,零个或多个)的相同唯一类型元素(数据项)组成的序列,元素的类型可以是任意的原始类型和自定义类型,且这些元素已经按照在数组中的位置进行了自动索引编号。因 Go 语言数组不支持动态创建,长度固定,所以更适合原始预置类数据的定义,需要有足够动态特性的请使用后面章节介绍的切片。

一维数组

  数组元素不再是数组的数组,只有一层数组结构,称之为一维数组。也是最常用最基本的数组形式。

一维数组的声明及初始化

  声明数组需要指定元素个数和元素类型,完整声明语法格式如下:
  var 变量名 [长度]元素数据类型
  ● 变量名:声明的数组变量的名称,符合语法规则的任意名字。
  ● 长度:元素个数,也称之为数组大小,表示声明的这个数组有多少个元素,必须是整数。
  ● 元素数据类型:数组内元素的数据类型,可以是任何基本类型、自定义类型,也可以是数组(但就成了多维数组)。

// test01 项目的 main 包,文件名 main.go
package main

import (
	"fmt"
)

// 主函数,程序入口
func main() {
	var a [5]int                   // 声明有5个元素的 int 数组,所有元素初始化为 0
	var b [4]string                // 声明有4个元素的 string 数组,所以元素初始化为空字符串
	var c = [2]float32{12.1, 23.6} // 声明有2个元素的 float32 数组,初始化元素分别为 12.1、23.6
	d := [2]string{"abc", "efg"}   // 声明有2个元素的 string 数组,初始化元素分别为 “abc” 和 “efg”
	e := [5]int{56, 39}            // 声明有5个元素的 int 数组,初始化第1、2个元素分别为 56、39,其他元素为 0
	f := [5]int{2: 56, 3: 39}      // 声明有5个元素的 int 数组,初始化第2、3个元素分别为 56、39,其他元素为 0
	g := [...]int{56, 39}          // 声明 int 数组,初始化元素分别为 56、39,数组长度是编译器推导出来的有2个元素

	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(c)
	fmt.Println(d)
	fmt.Println(e)
	fmt.Println(f)
	fmt.Println(g)
}

  第10、11行,完整格式声明,只声明没有赋值,会自动初始化为元素类型的零值,所以 int 类型的各元素被初始化为 0,string 类型的被初始化为空字符串。

  第12行,完整格式声明,并初始化各元素的值。声明有 2 个元素就在类型后面的花括号内写几个值,中间用逗号隔开。

  第13~16行,都是在声明局部变量时使用的格式,编译器根据元素值的类型自动推导出类型。

  第14行,声明的是有 5 个元素,但是花括号内只有两个值,那就是代表这是前两个的值,后面剩余的就是类型的零值。声明的是 int 类型,那其余元素就是 0 值。

  第15行,同样是声明了5个元素,但花括号只有两个值。注意这两个值是定义了索引号的,数组的索引号是从 0 开始的,所以 2: 56 是表示 2 号元素为 56,3: 39 是表示 3 号元素为 39。那么剩下的 0号、1号、4号 三个元素就是 0 了。

  第16行,使用 … 表示不提前声明数量,有初始化的元素数量决定,这里编译器会推导出是有两个元素的 int 数组。

  上述代码编译运行结果如下:

[0 0 0 0 0]
[   ]
[12.1 23.6]
[abc efg]
[56 39 0 0 0]
[0 0 56 39 0]
[56 39]

访问一维数组的元素

  对数组元素的访问是通过方括号加下标(索引号、位置)来进行的,索引号是从 0 开始,具体见如下示例:

// test01 项目的 main 包,文件名 main.go
package main

import (
	"fmt"
)

// 主函数,程序入口
func main() {
	arr := [...]int{10, 56, 39}

	fmt.Println(arr)    // 打印输出 arr 整个数组
	fmt.Println(arr[0]) // 打印输出数组 arr 的 0 号元素(第 1 个元素)
	fmt.Println(arr[2]) // 打印输出数组 arr 的 2 号元素(第 3 个元素)
	arr[0] = 101        // 将 arr 的 0 号元素赋值为 101
	arr[2] = 103        // 将 arr 的 2 号元素赋值为 103
	fmt.Println(arr)    // 打印输出 arr 整个数组
}

上述代码编译运行结果如下:

[10 56 39]
10
39
[101 56 103]

获取一维数组的长度

  如何获取数组的长度(元素个数),使用 Go 语言内置的函数 len() 即可:

arr := [3]int
n := len(arr)   // 此时变量 n 等于 3,为 int 类型

数组的比较判断

  数组也是可以通过 ==、!= 进行比较判断的,但是必须是同长度同类型的才可以比较,否则会报错。应为长度也是数组的一部分,所以长度不同的两个数组,不属于完全相同的两个类型。

// test01 项目的 main 包,文件名 main.go
package main

import (
	"fmt"
)

// 主函数,程序入口
func main() {
	a1 := [3]int{10, 56, 39}
	a2 := [3]int{10, 56, 39}
	a3 := [3]int{82, 56, 39}
	//a4 := [2]int{10, 56}
	//a3 := [2]string{"ab", "cd"}

	fmt.Println(a1 == a2)
	fmt.Println(a1 == a3)
	//fmt.Println(a1 == a4)
	//fmt.Println(a4 == a5)
}

  上述代码编译运行结果如下:

true
false

  上述代码如果放开注释,那么最后两行代码就会报错,因为它们之间长度或类型不一致,是无法比较的。

一维数组的遍历

  数组的遍历就是依次获取数组中所有的元素,有两个方法,一个是使用 for 计数循环,一个是使用 for range 循环:

// test01 项目的 main 包,文件名 main.go
package main

import (
	"fmt"
)

// 主函数,程序入口
func main() {
	arr := [...]int{10, 56, 39}

	fmt.Println("使用 for 循环计数方法遍历")

	// 遍历数组的方法一
	n := len(arr)
	for i := 0; i < n; i++ {
		fmt.Println("索引:", i, ",值:", arr[i])
	}

	fmt.Println("使用 for rande方法遍历")

	// 遍历数组的方法二
	for k, v := range arr {
		fmt.Println("索引:", k, ",值:", v)
	}

	// 遍历数组的方法二(只用值不用索引)
	for _, v := range arr {
		fmt.Println("值:", v)
	}
}

上述代码编译运行结果如下:

使用 for 循环计数方法遍历
索引: 0 ,值: 10
索引: 1 ,值: 56
索引: 2 ,值: 39
使用 for rande方法遍历
索引: 0 ,值: 10
索引: 1 ,值: 56
索引: 2 ,值: 39
值: 10
值: 56
值: 39

  遍历的方法一是要首先得到数组的长度(第15行),然后定义 for 循环的循环次数。循环计数变量初始化为 0,刚好与数组的第一个元素的索引号相同。接下来循环变量 i 是递增的,用 i 做取数组元素值的下标,就依次取出每个元素的值了。而 i 的值就刚好是索引号。

  遍历的方法二没有使用循环计数变量,而是使用了 range 关键字,将循环次数自动限定为其后面的数组长度,然后从0号索引位置开始,依次递增循环。每次循环都会返回当前的索引号和元素值,k 和 v就是分别接收这两个数据的。第一个是索引号,第二个是元素值。

  在某些应用场景下,我们可能用不到索引号,只需要元素值就可以了。如果这个时候我们要使用方法二进行遍历该如何接两个返回值呢?如果我们正常接了,但是又没有使用 k,那么编译时会报错。这种情况就该占位标识符 “_” 登场了,使用下划线占位原来 k 的位置,这样接到的值就会直接被抛弃,不会要求后面必须使用。所有有了最后的那段代码。

  如果使用 for range 方法只要循环索引号,将第28行代码中 := 左侧的两个变量改成只有一个变量,那么这个变量接的就是索引号,就没有元素值传出来了。

二维(多维)数组

  一个数组的元素还是个数组,而元素数组的元素不再是数组的数组,有两层数组结构,称之为二维数组。那么有这类三层数组结构的就叫三维数组,依次类推。我们通常将这些不只有一层数组结构的数组统称多维数组。了解了二维数组的,那么其他多维数组就可以触类旁通了。

二维数组的声明、初始化、元素访问

  上面了解了一维数组的基本结构和概念,那么对二维数组就很容易理解了,就是一维数组的镶嵌叠加,基本特性与一维数组相同。这里直接上演示代码:

// test01 项目的 main 包,文件名 main.go
package main

import (
	"fmt"
)

// 主函数,程序入口
func main() {
	var arr1 [2][2]int // 声明一个二维数组,第一维有两个元素,第二维有两个元素,没有赋值默认最终元素值是 0
	arr2 := [3][2]int{ // 声明一个二维数组,第一维有三个元素,但只给了两个值
		{10, 56},      // 没有索引号,就默认从 0 号索引开始排列依次赋值
		2: {72, 31},   // 有索引号的,按照索引位置赋值
	}

	fmt.Println("数组 arr1:", arr1)
	fmt.Println("数组 arr2:", arr2)
	fmt.Println("arr2第一个元素:", arr2[0])
	fmt.Println("arr2第一个元素内的第二个元素:", arr2[0][1])

	arr2[0][1] = 99 // 将 arr2 第一个元素里面的第二个元素的值修改为 99

	fmt.Println("修改后的数组 arr2:", arr2)

	arr1[1] = [2]int{66, 87} // 将 arr1 第二个元素整体赋值一个新的数组格式的数据

	fmt.Println("修改后的数组 arr1:", arr1)
}

  上述代码编译运行结果如下:

数组 arr1: [[0 0] [0 0]]
数组 arr2: [[10 56] [0 0] [72 31]]
arr2第一个元素: [10 56]
arr2第一个元素内的第二个元素: 56
修改后的数组 arr2: [[10 99] [0 0] [72 31]]
修改后的数组 arr1: [[0 0] [66 87]]

  **从结果就可以看出,二维数组就是等于一维数组的元素又是一个一维数组。**所以这里就不再过多描述了,如果理解了上面的一维数组,再看这段代码就很容易理解二维数组了。

获取二维数组的长度

  二维数组有两个长度,及第一维有几个元素,第二维(第一维的元素)有几个元素,同样都可以使用 len() 内置函数获取到:

n1 := len(arr2)     // 放到上例代码中,n1 的值就是 3
n2 := len(arr2[0])  // 放到上例代码中,n2 的值就是 2

二维数组的遍历

  二维数组的遍历方法与一维数组原理相同。只是因为多了一层数组,若要遍历第二维的元素,那么循环内就要嵌套一个循环,可使用的循环方法与一维数组相同。下面用 for range 演示遍历过程:

// test01 项目的 main 包,文件名 main.go
package main

import (
	"fmt"
)

// 主函数,程序入口
func main() {
	arr := [...][2]int{
		{10, 56},
		{72, 31},
	}

	fmt.Println("数组 arr:", arr)

	for k1, v1 := range arr {
		for k2, v2 := range v1 {
			fmt.Println(k1, "->", k2, ":", v2)
		}
	}
}

  上述代码编译运行结果如下:

数组 arr: [[10 56] [72 31]]
0 -> 010
0 -> 156
1 -> 072
1 -> 131

  在第18行,因为 v1 是数组 arr 第一维的元素,所以它还是个数组,那就可以继续使用 for range 遍历。

  注意,Go语言的数组是不支持动态增加和删除元素的,有此需求需要使用后面章节介绍的切片。
.
.
上一节:Go/Golang语言学习实践[回顾]教程17–详解Go语言复合数据类型之指针 Pointer

下一节:Go/Golang语言学习实践[回顾]教程19–详解Go语言复合数据类型之切片 []
.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学为所用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值