Skip to content

数组

数组的定义

数组是一种存储相同数据类型的元素的定长容器,在 Go 语言中有一维数组和多维数组。

先介绍一维数组的语法格式和示例。

语法格式

go
var 数组名 [长度]数据类型
go
// 使用var关键字定义
var 数组名 [长度]数据类型 = [长度]数据类型{元素1, 元素2, 元素3, ..., 元素n}

// 使用类型推断的方式
var 数组名 = [长度]数据类型{元素1, 元素2, 元素3, ..., 元素n}

// 使用简短定义的方式
数组名 := [长度]数据类型{元素1, 元素2, 元素3, ..., 元素n}
go
var 数组名 [长度]数据类型 
数组名 = [长度]数据类型{元素1, 元素2, 元素3, ..., 元素n}

示例

go
package main

import "fmt"

func main() {
	// 定义数组语法:var 数组名 [长度]数据类型
	var arr1 [5]int
	fmt.Printf("arr1 = %v\n", arr1) // [0 0 0 0 0]

	// 定义数组并初始化
	arr2 := [5]bool{true, false, true, false, true}
	fmt.Printf("arr2 = %v\n", arr2)

	// 定义数组并初始化
	var arr3 [5]string
	arr3 = [5]string{"a", "b", "c", "d", "e"}
	fmt.Printf("arr3 = %v\n", arr3)
}

访问数组元素

数组的每一个元素都可以通过下标索引的方式来访问。

语法格式

go
// 索引不存在,编译不通过
数组名[索引]

示例

go
package main

import "fmt"

func main() {
	// 创建一个int类型长度为6的数组
	var arr1 [5]int = [5]int{13, 25, 33, 46, 55}
	// 通过数组索引访问数组元素
	fmt.Println(arr1[0]) // 13
	fmt.Println(arr1[1]) // 25
	fmt.Println(arr1[2]) // 33
	fmt.Println(arr1[3]) // 46
	fmt.Println(arr1[4]) // 55

	// 访问不存在的索引
	// fmt.Println(arr1[5]) // 编译不通过
}

获取数组长度

索引的范围从0开始到数组的长度减1的位置结束,可以通过 len() 函数来获取数组的长度【数组中的元素个数】。

语法格式

go
// v可以是以下几种类型: array、slice、string、map、channel
len(v)

示例

go
package main

import "fmt"

func main() {
	// 使用len()函数获取数组长度
	var arr = [10]int{13, 23, 36, 44, 58, 64, 72, 88, 91}
	fmt.Printf("数组长度为:%d\n", len(arr)) // 数组长度为:10
}

数组的初始化元素默认值

在初始化数组时每一个元素的初始化都是数据类型的初始值,数值型: 0、字符串: ""、布尔类型: false、浮点类型: 0.0等。

示例

go
package main

import "fmt"

func main() {
	// int类型的数组
	var a1 [3]int
	fmt.Printf("a1 = %v\n", a1) // a1 = [0 0 0]

	// bool类型的数组
	var a2 [3]bool
	fmt.Printf("a2 = %v\n", a2) // a2 = [false false false]

	// string类型的数组
	var a3 [3]string
	fmt.Printf("a3 = %v\n", a3) // a3 = [   ]

	// float64类型的数组
	var a4 [3]float64
	fmt.Printf("a4 = %v\n", a4) // a4 = [0 0 0]
}

使用...替代数组长度

在定义数组并初始化数组元素时,可以使用 ... 来替代数组的长度,... 表示数组的长度根据数组的元素个数来推断数组的长度。

示例

go
package main

import "fmt"

func main() {
	// 在定义数组并初始化数组元素时可以使用...来替代数组的长度
	var a = [...]int{1, 2, 3, 4, 5} // 定义数组并初始化数组元素
	fmt.Printf("a = %v\n", a)       // a = [1 2 3 4 5]
}

比较数组内元素是否相同

如果两个数组类型相同(长度相同、数据类型相同)的情况下,可以使用 == 或者 != 的方式来判断两个数组是否相同,只有当两个数组的所有元素都是相等的时候数组才是相等的,不能比较两个类型不同的数组,否则程序将无法完成编译。

示例

go
package main

import "fmt"

func main() {
	// 使用==判断两个数组是否相同
	a1 := [...]int{1, 2, 3}
	a2 := [...]int{1, 2, 3}
	fmt.Printf("a1类型:%T\n", a1)
	fmt.Printf("a2类型:%T\n", a2)
	fmt.Printf("a1 == a2 结果:%t\n", (a1 == a2))
	// 使用==判断两个数组是否相同
	a3 := [...]int{11, 2, 3}
	fmt.Printf("a3类型:%T\n", a3)
	fmt.Printf("a1 == a3 结果:%t\n", (a1 == a3))
	// 使用!=判断两个数组是否不相同
	fmt.Printf("a1 != a2 结果:%t\n", (a1 != a2))
	fmt.Printf("a1 != a3 结果:%t\n", (a1 != a3))

	// 注意事项:必须是两个数组类型相同才能进行比较。【数据类型相同:长度相同、数据类型相同】
	// a4 := [...]int{1, 2, 3, 4}
	// fmt.Printf("a1 == a4 结果:%t\n", (a1 == a4)) // 编译不通过
}

遍历数组

可以使用 for 语句或者 for range 语句来对数组进行遍历操作。

示例:

go
package main

import "fmt"

func main() {
	// 定义一个字符串数组长度为5
	s1 := [5]string{"Go", "Java", "C++", "Python", "Rust"}
	// 使用for循环遍历数组
	for i := 0; i < len(s1); i++ {
		println(s1[i])
	}
	fmt.Println("========================")
	// 使用for range遍历数组
	for index, value := range s1 {
		println(index, value)
	}
}

数组是值类型

在Go语言中数组是值类型,而不是引用类型,也就是当一个数组被赋值给另一个变量时,实际上是创建了一个新的数组,并将原来数组的值拷贝到了这个新数组中【值拷贝】,如果对新数组进行修改,原数组不会受影响。

示例

go
package main

import "fmt"

func main() {
	// 数组是值类型
	arr1 := [3]int{1, 2, 3}
	arr2 := arr1

	var arr3 [3]int
	arr3 = arr1
	// 打印arr1、arr2、arr3的内存地址和值
	fmt.Printf("arr1地址:%p,arr1值:%#v\n", &arr1, arr1)
	fmt.Printf("arr2地址:%p,arr2值:%#v\n", &arr2, arr2)
	fmt.Printf("arr3地址:%p,arr3值:%#v\n", &arr3, arr3)

	fmt.Println("=======================================")

	// 对arr2数组的第二个元素进行修改
	arr2[1] = 200
	// 对arr3数组的第三个元素进行修改
	arr3[2] = 300

	// 再打印arr1、arr2、arr3的内存地址和值
	fmt.Printf("arr1地址:%p,arr1值:%#v\n", &arr1, arr1)
	fmt.Printf("arr2地址:%p,arr2值:%#v\n", &arr2, arr2)
	fmt.Printf("arr3地址:%p,arr3值:%#v\n", &arr3, arr3)
}

长度也是数组类型组成部分

数组的长度也是数组类型的组成部分,因此 [5]int[6]int 是两种不同的数组类型。

示例

go
package main

import "fmt"

func main() {
	// [5]int和[6]int是两种不同的数组类型
	a1 := [5]int{1, 2, 3, 4, 5}
	fmt.Printf("a1的值:%v\n", a1)
	// a1 = [6]int{1, 2, 3, 4, 5, 6} // 编译不通过
	a1 = [5]int{11, 22, 33, 44, 55}
	fmt.Printf("a1的值:%v\n", a1)
}

多维数组

在 Go 语言中,多维数组是由数组的数组组成的。最常见的多维数组是二维数组,但是你可以创建任意数量的维度。

多维数组主要用于场景,其中需要存储和操作表格数据或其他形式的网格,例如在矩阵运算或图形计算中。然而,当你需要一个动态大小的多维结构时,应该使用切片的切片。

语法格式

go
var 变量名 [长度1][长度2]...[长度n] 数据类型

示例

go
package main

import "fmt"

func main() {
	// 定义一个[4][3]的二维数组。(多维数组同理)
    // 有4个一维数组,每个一维数组的长度都是3
	var array [4][3]int
	array = [4][3]int{
		{1, 2, 3},    // [0,0] [0,1] [0,2]
		{4, 5, 6},    // [1,0] [1,1] [1,2]
		{7, 8, 9},    // [2,0] [2,1] [2,2]
		{10, 11, 12}, // [3,0] [3,1] [3,2]
	}
	for i := 0; i < len(array); i++ {
		for j := 0; j < len(array[i]); j++ {
			fmt.Printf("arr[%d][%d]:%v\n", i, j, array[i][j])
		}
	}
}
go
package main

import "fmt"

func main() {
	// 定义一个三维数组
	var array3D [2][3][4]int
	// 给数组赋值
	// 2 表示这个三维数组有 2 个二维数组。
	// 3 表示每个二维数组有 3 个一维数组(行)。
	// 4 表示每个一维数组有 4 个元素(列)。
	// 个数计算:2 * 3 * 4 = 24
	array3D = [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(array3D)
}

使用数组注意事项

数组使用时的注意事项

  • 固定大小:Go中的数组是固定大小的。数组的长度是其类型的一部分,一旦声明,数组的大小就不能改变。
  • 值类型:Go中的数组是值类型,这意味着当它们被赋值给一个新变量或者作为参数传递给函数时,实际上会复制整个数组。如果数组比较大,这可能会导致性能问题。
  • 初始化:你可以在声明数组时初始化数组元素。如果不初始化,默认情况下,数值数组元素将被初始化为0,字符串数组为空字符串,布尔数组元素为false。
  • 索引:数组的索引从0开始,尝试访问超出数组长度范围的索引会产生运行时错误(out of range)。
  • 多维数组:在 Go 中,可以创建多维数组。在使用时,你要为每个维度提供大小,并记住它们的索引也是从0开始的。
  • 迭代:可以使用for循环或for...range结构来迭代数组。
  • 内存布局:数组中的元素在内存中是连续存放的。

请记住,在需要动态大小集合的时候,应该使用切片(slice),而不是数组,因为切片比数组更加灵活。

根据 MIT 许可证发布