数组是 Go 语言中最基本的数据结构之一。本章将详细介绍数组的声明、初始化、遍历和使用方法。
数组是固定长度的、存储相同类型元素的序列。
可以把数组想象成一排连续的储物柜:
索引: 0 1 2 3 4
┌──────┬──────┬──────┬──────┬──────┐
数组: │ 10 │ 20 │ 30 │ 40 │ 50 │
└──────┴──────┴──────┴──────┴──────┘
| 特点 | 说明 |
|---|---|
| 固定长度 | 声明后长度不可改变 |
| 相同类型 | 所有元素必须是同一类型 |
| 值类型 | 赋值和传参会复制整个数组 |
| 连续内存 | 元素在内存中连续存储 |
var 数组名 [长度]类型
示例:
package main
import "fmt"
func main() {
var nums [5]int
var names [3]string
var flags [4]bool
fmt.Printf("nums: %v\n", nums)
fmt.Printf("names: %v\n", names)
fmt.Printf("flags: %v\n", flags)
}
输出:
nums: [0 0 0 0 0]
names: [ ]
flags: [false false false false]
注意:数组声明后,元素会自动初始化为零值。
var 数组名 = [长度]类型{元素1, 元素2, ...}
示例:
package main
import "fmt"
func main() {
var nums = [5]int{10, 20, 30, 40, 50}
var names = [3]string{"张三", "李四", "王五"}
fmt.Printf("nums: %v\n", nums)
fmt.Printf("names: %v\n", names)
}
输出:
nums: [10 20 30 40 50]
names: [张三 李四 王五]
数组名 := [长度]类型{元素1, 元素2, ...}
示例:
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
names := [3]string{"张三", "李四", "王五"}
fmt.Printf("nums: %v\n", nums)
fmt.Printf("names: %v\n", names)
}
使用 ... 让编译器自动计算长度:
package main
import "fmt"
func main() {
nums := [...]int{10, 20, 30, 40, 50}
names := [...]string{"张三", "李四", "王五"}
fmt.Printf("nums 长度: %d, 值: %v\n", len(nums), nums)
fmt.Printf("names 长度: %d, 值: %v\n", len(names), names)
}
输出:
nums 长度: 5, 值: [10 20 30 40 50]
names 长度: 3, 值: [张三 李四 王五]
可以指定索引位置初始化:
package main
import "fmt"
func main() {
nums := [5]int{0: 10, 2: 30, 4: 50}
fmt.Printf("nums: %v\n", nums)
}
输出:
nums: [10 0 30 0 50]
使用索引访问数组元素,索引从 0 开始:
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
fmt.Printf("第一个元素: %d\n", nums[0])
fmt.Printf("第三个元素: %d\n", nums[2])
fmt.Printf("最后一个元素: %d\n", nums[4])
nums[0] = 100
fmt.Printf("修改后的第一个元素: %d\n", nums[0])
}
输出:
第一个元素: 10
第三个元素: 30
最后一个元素: 50
修改后的第一个元素: 100
访问超出范围的索引会报错:
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
fmt.Println(nums[5])
}
错误信息:
invalid array index 5 (out of bounds for 5-element array)
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
for i := 0; i < len(nums); i++ {
fmt.Printf("索引: %d, 值: %d\n", i, nums[i])
}
}
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
for index, value := range nums {
fmt.Printf("索引: %d, 值: %d\n", index, value)
}
}
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
fmt.Println("只要值:")
for _, value := range nums {
fmt.Printf("值: %d\n", value)
}
fmt.Println("\n只要索引:")
for index := range nums {
fmt.Printf("索引: %d\n", index)
}
}
Go 支持多维数组,最常见的是二维数组。
package main
import "fmt"
func main() {
var matrix [3][4]int
for i := 0; i < 3; i++ {
for j := 0; j < 4; j++ {
matrix[i][j] = i*4 + j + 1
}
}
fmt.Println("二维数组:")
for _, row := range matrix {
fmt.Println(row)
}
}
输出:
二维数组:
[1 2 3 4]
[5 6 7 8]
[9 10 11 12]
package main
import "fmt"
func main() {
matrix := [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
fmt.Println("矩阵:")
for _, row := range matrix {
fmt.Println(row)
}
}
输出:
矩阵:
[1 2 3]
[4 5 6]
[7 8 9]
数组是值类型,赋值和传参会复制整个数组:
package main
import "fmt"
func modifyArray(arr [3]int) {
arr[0] = 100
fmt.Printf("函数内: %v\n", arr)
}
func main() {
nums := [3]int{1, 2, 3}
fmt.Printf("原始数组: %v\n", nums)
modifyArray(nums)
fmt.Printf("调用后: %v\n", nums)
}
输出:
原始数组: [1 2 3]
函数内: [100 2 3]
调用后: [1 2 3]
注意:函数内修改的是副本,不影响原数组。
如果需要修改原数组,传递指针:
package main
import "fmt"
func modifyArray(arr *[3]int) {
arr[0] = 100
fmt.Printf("函数内: %v\n", *arr)
}
func main() {
nums := [3]int{1, 2, 3}
fmt.Printf("原始数组: %v\n", nums)
modifyArray(&nums)
fmt.Printf("调用后: %v\n", nums)
}
输出:
原始数组: [1 2 3]
函数内: [100 2 3]
调用后: [100 2 3]
相同类型的数组可以使用 == 和 != 比较:
package main
import "fmt"
func main() {
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
c := [3]int{1, 2, 4}
fmt.Printf("a == b: %v\n", a == b)
fmt.Printf("a == c: %v\n", a == c)
}
输出:
a == b: true
a == c: false
注意:长度不同的数组是不同类型,无法比较。
使用 len() 获取数组长度:
package main
import "fmt"
func main() {
nums := [5]int{10, 20, 30, 40, 50}
fmt.Printf("数组长度: %d\n", len(nums))
}
package main
import "fmt"
func main() {
nums := [...]int{64, 34, 25, 12, 22, 11, 90}
max, min := nums[0], nums[0]
for _, num := range nums {
if num > max {
max = num
}
if num < min {
min = num
}
}
fmt.Printf("数组: %v\n", nums)
fmt.Printf("最大值: %d\n", max)
fmt.Printf("最小值: %d\n", min)
}
输出:
数组: [64 34 25 12 22 11 90]
最大值: 90
最小值: 11
package main
import "fmt"
func main() {
nums := [...]int{64, 34, 25, 12, 22, 11, 90}
fmt.Printf("排序前: %v\n", nums)
n := len(nums)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if nums[j] > nums[j+1] {
nums[j], nums[j+1] = nums[j+1], nums[j]
}
}
}
fmt.Printf("排序后: %v\n", nums)
}
输出:
排序前: [64 34 25 12 22 11 90]
排序后: [11 12 22 25 34 64 90]
package main
import "fmt"
func main() {
nums := [...]int{10, 20, 30, 40, 50}
sum := 0
for _, num := range nums {
sum += num
}
avg := float64(sum) / float64(len(nums))
fmt.Printf("数组: %v\n", nums)
fmt.Printf("总和: %d\n", sum)
fmt.Printf("平均值: %.2f\n", avg)
}
输出:
数组: [10 20 30 40 50]
总和: 150
平均值: 30.00
| 局限 | 说明 |
|---|---|
| 固定长度 | 无法动态添加或删除元素 |
| 值类型 | 传参会复制整个数组,效率低 |
| 类型固定 | 只能存储一种类型 |
解决方案:使用切片(Slice),它更灵活,是 Go 中更常用的数据结构。
本章学习了 Go 语言的数组:
| 知识点 | 说明 |
|---|---|
| 声明 | var arr [n]T 或 arr := [...]T{...} |
| 访问 | arr[index],索引从 0 开始 |
| 遍历 | for-range 循环 |
| 长度 | len(arr) |
| 类型 | 值类型,赋值和传参会复制 |
| 比较 | 相同类型可以用 == 比较 |