【golang学习之旅】复杂数据类型——数组

系列文章

【golang学习之旅】使用VScode安装配置Go开发环境
【golang学习之旅】报错:a declared but not used
【golang学习之旅】Go 的基本数据类型
【golang学习之旅】深入理解字符串string数据类型
【golang学习之旅】go mod tidy
【golang学习之旅】记录一次 panic case : reflect: reflect.Value.SetInt using unaddressable value
【golang学习之旅】记录一次 error case : full error output: cc1: error: unrecognized command line option
【golang学习之旅】Go程序快速开始 & Go程序开发的基本注意事项
【golang学习之旅】Go语言常用转义字符
【golang学习之旅】Go中的变量(1)
【golang学习之旅】Go中的变量------基本数据类型(1)
【golang学习之旅】Go中的变量------基本数据类型(2)
【golang学习之旅】复杂数据类型------指针 & 函数
【golang学习之旅】延迟调用------defer


  • 系列文章
  • [1. 概念](#1. 概念)
  • [2. 数组的声明与初始化](#2. 数组的声明与初始化)
    • [2.1 声明数组](#2.1 声明数组)
    • [2.2 其他类型数组](#2.2 其他类型数组)
    • [2.3 空数组](#2.3 空数组)
  • [3. 访问与操作数组](#3. 访问与操作数组)
    • [3.1 访问数组](#3.1 访问数组)
    • [3.2 遍历数组](#3.2 遍历数组)

1. 概念

有其他编程语言基础的同学应该对数组不陌生。数组是一种固定长度、同类型元素的有序集合

注意事项:如果我们想让数组元素类型为任意类型的话可以使用空接口(后面的文章会提到)作为类型

与许多其他编程语言中的数组类似,Go语言中的数组也通过索引 来访问其元素,索引从0开始,直到数组长度减1。(数组以 0 开始在所有类 C 语言中是相似的)。数组的类型由其元素类型和长度共同决定 ,因此[5]int和[10]int被视为两种完全不同的类型。因此在 Go 语言中很少直接使用数组(不同长度的数组因为类型不同无法直接赋值)。和数组对应的类型是切片,切片是可以动态增长和收缩的序列,切片的功能也更加灵活,但是要理解切片的工作原理还是要先理解数组。

下面介绍在Go语言中数组是如何声明和使用的。


2. 数组的声明与初始化

2.1 声明数组

Go语言中声明数组的语法非常直观:

go 复制代码
var arrayName [length]elementType

其中,arrayName是数组的名称,length是数组的长度,elementType是数组元素的类型。例如,声明一个包含5个整数的数组:

go 复制代码
var numbers [5]int // 定义长度为 5 的 int 型数组, 元素全部为 0

在声明数组时,也可以同时初始化其元素:

go 复制代码
var numbers = [5]int{1, 2, 3, 4, 5}

或者,使用更简洁的语法:

go 复制代码
numbers := [5]int{1, 2, 3, 4, 5}

还有其他的定义方法,比如:

go 复制代码
var b = [...]int{1, 2, 3}       // 定义长度为 3 的 int 型数组, 元素为 1, 2, 3
var c = [...]int{2: 3, 1: 2}    // 定义长度为 3 的 int 型数组, 元素为 0, 2, 3
var d = [...]int{1, 2, 4: 5, 6} // 定义长度为 6 的 int 型数组, 元素为 1, 2, 0, 0, 5, 6
  • 第一种方式定义数组,可以在定义的时候顺序指定全部元素的初始化值,数组的长度根据初始化元素的数目自动计算。
  • 第二种方式是以索引的方式来初始化数组的元素,因此元素的初始化值出现顺序比较随意。这种初始化方式和 map[int]Type 类型的初始化语法类似。数组的长度以出现的最大的索引为准,没有明确初始化的元素依然用零值初始化。
  • 第三种方式是混合了第二种和第三种的初始化方式,前面两个元素采用顺序初始化,第三第四个元素零值初始化,第五个元素通过索引初始化,最后一个元素跟在前面的第五个元素之后采用顺序初始化。

2.2 其他类型数组

数组不仅仅可以用于数值类型,还可以定义字符串数组、结构体数组、函数数组、接口数组、管道数组等等:

go 复制代码
// 字符串数组
var s1 = [2]string{"hello", "world"} // 显式指定长度为2
var s2 = [...]string{"你好", "世界"} // 使用...自动推导长度
var s3 = [...]string{1: "世界", 0: "你好", }// 使用...自动推导长度,并且显式地指定了元素的索引和值,这种方式允许我们以非顺序的方式初始化数组元素

// 结构体数组
var line1 [2]image.Point
var line2 = [...]image.Point{image.Point{X: 0, Y: 0}, image.Point{X: 1, Y: 1}}
var line3 = [...]image.Point{{0, 0}, {1, 1}}

// 图像解码器数组
var decoder1 [2]func(io.Reader) (image.Image, error)
var decoder2 = [...]func(io.Reader) (image.Image, error){
    png.Decode,
    jpeg.Decode,
}

// 接口数组
var unknown1 [2]interface{}
var unknown2 = [...]interface{}{123, "你好"}

// 管道数组
var chanList = [2]chan int{}

2.3 空数组

我们还可以定义一个空的数组:

go 复制代码
var d [0]int       // 定义一个长度为 0 的数组
var e = [0]int{}   // 定义一个长度为 0 的数组
var f = [...]int{} // 定义一个长度为 0 的数组

长度为 0 的数组在内存中并不占用空间。空数组虽然很少直接使用,但是可以用于强调某种特有类型的操作时避免分配额外的内存空间,比如用于管道的同步操作:


3. 访问与操作数组

3.1 访问数组

这里要区分一下Go语言中的数组和C语言中的数组的区别。

Go 语言中数组是值类型。一个数组变量即表示整个数组,它并不是隐式的指向第一个元素的指针(比如 C 语言的数组),而是一个完整的值。这意味着当你将数组赋值给另一个变量或将其作为函数参数传递时,实际上是在复制整个数组。这可能导致在处理大型数组时性能下降。为了避免复制数组带来的开销,可以传递一个指向数组的指针,但是数组指针并不是数组。

比如:

go 复制代码
var a = [...]int{1, 2, 3} // a 是一个数组
var b = &a                // b 是指向数组的指针

fmt.Println(a[0], a[1])   // 打印数组的前 2 个元素
fmt.Println(b[0], b[1])   // 通过数组指针访问数组元素的方式和数组类似

for i, v := range b {     // 通过数组指针迭代数组的元素
    fmt.Println(i, v)
}
  • 其中 b 是指向 a 数组的指针,但是通过 b 访问数组中元素的写法和 a 类似的。其实数组指针类型除了类型和数组不同之外,通过数组指针操作数组的方式和通过数组本身的操作类似,而且数组指针赋值时只会拷贝一个指针。但是数组指针类型依然不够灵活,因为数组的长度是数组类型的组成部分,指向不同长度数组的数组指针类型也是完全不同的

3.2 遍历数组

我们可以用 for 循环来迭代数组。下面常见的几种方式都可以用来遍历数组:

go 复制代码
    for i := range a {
        fmt.Printf("a[%d]: %d\n", i, a[i])
    }
    for i, v := range b {
        fmt.Printf("b[%d]: %d\n", i, v)
    }
    for i := 0; i < len(c); i++ {
        fmt.Printf("c[%d]: %d\n", i, c[i])
    }

for range 方式迭代的性能可能会更好一些,因为这种迭代可以保证不会出现数组越界的情形,每轮迭代对数组元素的访问时可以省去对下标越界的判断。

相关推荐
花酒锄作田4 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode