跳转到主要内容
模块 4 · 第 1 课(共 5)课程中的16/50~8 min
模块课程(1/5)

定长数组

在 Go 中,数组具有固定长度,并融入其类型:[N]T。 它是一个很少直接在应用程序代码中使用的原语 - 您将 几乎总是使用切片(下一课),它是动态的 数组的视图。

尽管如此,充分理解数组仍然至关重要:Go 中的一切都是构建的 在他们之上。

声明和初始化

Go
var a [3]int = [3]int{10, 20, 30}
b := [3]int{1, 2, 3}            // inference with :=
c := [3]int{}                   // all zero: [0, 0, 0]
d := [...]int{1, 2, 3, 4}       // length inferred = 4

数组的零值是声明长度的数组,其中每个 元素为零值:

Go
var nums [5]int  // [0 0 0 0 0]

索引和 len

Go
a := [3]int{10, 20, 30}
fmt.Println(a[0])      // 10
a[1] = 99
fmt.Println(len(a))    // 3

超出范围的访问会导致运行时恐慌(不是静默的未定义 就像C)中那样。

长度是类型的一部分

Go
var a [3]int
var b [4]int
// a = b   // ERROR: different types

[3]int 和 [4]int 是 不同的类型,即使两者都持有 int。这就是为什么数组很少传递给函数的原因:你必须 将长度硬编码到参数类型中。

按值复制

与切片(参考)和映射(参考)不同,数组是复制的 值:

Go
a := [3]int{1, 2, 3}
b := a               // copy
b[0] = 99
fmt.Println(a[0])    // 1 — a is unchanged

这同样适用于传递给函数时:函数接收它的 自己的副本。

什么时候使用数组?

  • 编译时已知的固定大小缓冲区(例如 MD5 的 [16]byte)。
  • 复合映射键(切片不是“可比较的”,数组是)。
  • 极致性能(无间接,缓存友好)。

对于 99% 的代码:使用切片。

尝试一下

锻炼#go.m4.l1.e1
尝试:0加载中...

将 a 声明为由 3 个整数组成的数组,其值为 10、20、30 并打印其长度。

正在加载编辑器...
显示提示

数组字面量:`[3]int{a, b, c}`。

3 次尝试后可用的解决方案

锻炼#go.m4.l1.e2
尝试:0加载中...

将 b 声明为 5 个整数(全部为零)的数组,并将 99 分配给位置 2。

正在加载编辑器...
显示提示

`var b [5]int` 开头为 [0 0 0 0 0]。

3 次尝试后可用的解决方案

Quiz#go.m4.l1.e3
准备好

[3]int 和 [4]int 是同一类型吗?

Go
var a [3]int
var b [4]int
// a = b ?
答案选项

回顾

  • [N]T:固定长度,类型的一部分。
  • 零值:每个元素都为零值。
  • [...]int{...} 让编译器推断长度。
  • 按值复制(包括内部函数)。
  • 超出范围 = 恐慌,而不是未定义。
  • 在实践中,使用切片,它是数组的视图。