ZetCode

Go 数组

最后修改于 2025 年 5 月 3 日

在本文中,我们将展示如何在 Golang 中使用数组。

Go 中的数组是共享相同数据类型的元素的集合。数组的大小是固定的,这意味着它们的长度在声明时确定,并且在程序执行期间不能修改——不能扩展也不能缩减。

数组元素使用从零开始的索引进行访问,第一个元素位于索引 0 处。这允许使用数组内元素的位置直接访问任何元素。默认情况下,当数组声明时没有指定值时,其元素将使用零值进行初始化,例如整数的 0,浮点数的 0.0,布尔值的 false,以及字符串类型的空字符串 ("")。

要获取数组中的元素总数,Go 提供了 len 函数,该函数返回其长度。此函数对于遍历数组或在执行操作之前验证其大小很有用。

由于数组的大小是固定的,Go 通常更倾向于使用 切片 (slices) 来进行更灵活的数据管理。切片在保持相似的索引行为的同时,提供了动态调整大小和其他功能。

声明数组

var a[n]T

我们声明一个长度为 n、类型为 T 的数组。

var a[5]int

这里我们声明一个包含五个整数的数组。

a := [5]int{1, 2, 3, 4, 5}

这是 Go 数组的简写声明和初始化。

数组初始化

以下示例显示了如何在 Go 中初始化数组。

main.go
package main

import "fmt"

func main() {

    var vals [2]int
    fmt.Println(vals)

    vals[0] = 1
    vals[1] = 2
    fmt.Println(vals)
}

在代码示例中,我们声明了一个整数数组;该数组可以容纳两个元素。

var vals [2]int
fmt.Println(vals)

[2]int 是整个类型,包括大小数字。开始时,数组包含 0。

vals[0] = 1
vals[1] = 2
fmt.Println(vals)

我们将两个值赋给数组。

$ go run main.go
[0 0]
[1 2]

数组字面量

Golang 有数组字面量;我们可以将数组的元素指定在 {} 括号之间。

main.go
package main

import "fmt"

func main() {

    vals := [5]int{1, 2, 3, 4, 5}
    fmt.Println(vals)

    vals2 := [5]int{1, 2, 3}
    fmt.Println(vals2)
}

在代码示例中,我们定义了两个数组,使用数组字面量。

vals := [5]int{1, 2, 3, 4, 5}

第一个数组有五个元素;所有元素都在 {} 括号之间初始化。

vals2 := [5]int{1, 2, 3}

这里我们只提供了五个元素中的三个;其余元素初始化为 0。

$ go run main.go
[1 2 3 4 5]
[1 2 3 0 0]

在数组字面量中,我们可以提供元素的索引。

main.go
package main

import "fmt"

func main() {

    vals := [5]int{1: 6, 2: 7, 4: 9}

    fmt.Println(vals)
}

在代码示例中,我们使用数组字面量初始化数组。为值提供了它们的索引;数组的其他元素被赋予 0 值。

$ go run main.go
[0 6 7 0 9]

推断数组长度

Go 可以使用数组字面量推断数组的长度。为此,我们使用省略号 ... 运算符。

main.go
package main

import "fmt"

func main() {

    vals := [...]int{ 1, 2, 3, 4, 5, 6 }
    fmt.Println(vals)
}

在代码示例中,我们在数组声明中使用 ...。这告诉 Go 从提供的数组字面量推断数组的长度。

$ go run main.go
[1 2 3 4 5 6]
注意: 当我们不指定数组大小时,并且不使用 ... 运算符时,我们实际上是在创建一个 Go 切片。

要在 Go 中提取类型信息,我们使用 reflect 包。

main.go
package main

import (
    "fmt"
    "reflect"
)

func main() {

    var a [5]int
    var b []int

    fmt.Println(reflect.ValueOf(a).Kind())
    fmt.Println(reflect.ValueOf(b).Kind())
}

a 是一个数组,而 b 是一个切片。

$ go run main.go
array
slice

数组长度

数组的长度由 len 函数确定。

main.go
package main

import "fmt"

func main() {

    words := [5]string{ "falcon", "sky", "earth", "cloud", "fox" }
    fmt.Println("There are", len(words), "words in the array")
}

在代码示例中,我们定义了一个字符串数组。我们打印数组中单词的数量。

$ go run main.go
There are 5 words in the array

数组索引

数组通过其索引进行访问。

main.go
package main

import "fmt"

func main() {

    var words[5]string

    words[0] = "falcon"
    words[1] = "sky"
    words[2] = "earth"
    words[3] = "cloud"
    words[4] = "fox"

    fmt.Println(words[0], words[1])
    fmt.Println(words)
}

在代码示例中,我们使用一个单词数组。

var words[5]string

我们声明了一个包含五个元素的字符串数组。

words[0] = "falcon"
words[1] = "sky"
words[2] = "earth"
words[3] = "cloud"
words[4] = "fox"

我们将五个单词放入数组。

fmt.Println(words[0], words[1])

我们打印数组的第一个和第二个元素。

fmt.Println(words)

我们打印整个数组。

$ go run main.go
falcon sky
[falcon sky earth cloud fox]

我们可以使用 : 冒号字符来获取数组的一部分。

main.go
package main

import "fmt"

func main() {

    words := [...]string{ "falcon", "sky", "earth", "cloud", "fox" }

    fmt.Println(words[0:2])
    fmt.Println(words[1:])
    fmt.Println(words[:])
    fmt.Println(words[:len(words)])
}

示例打印了已定义数组的各个部分。

$ go run main.go
[falcon sky]
[sky earth cloud fox]
[falcon sky earth cloud fox]
[falcon sky earth cloud fox]

数组迭代

使用 for 循环,我们可以在 Go 中迭代数组元素。

main.go
package main

import "fmt"

func main() {

    words := []string{ "falcon", "sky", "earth", "cloud", "fox" }

    for i := 0; i < len(words); i++ {

        fmt.Println(words[i])
    }

    for idx, e := range words {

        fmt.Println(idx, "=>", e)
    }

    j := 0

    for range words {

        fmt.Println(words[j])
        j++
    }
}

示例使用三种 for 循环形式来迭代单词数组。

$ go run main.go
falcon
sky
earth
cloud
fox
0 => falcon
1 => sky
2 => earth
3 => cloud
4 => fox
falcon
sky
earth
cloud
fox

Go 数组是值类型

与其他语言不同,Go 中的数组是值类型。这意味着当我们向新变量赋值一个数组或将数组传递给函数时,整个数组都会被复制。

main.go
package main

import "fmt"

func main() {

    vals := [...]int{ 1, 2, 3, 4, 5, 6 }
    vals2 := vals

    vals2[0] = 11
    vals2[1] = 22

    fmt.Println(vals)
    fmt.Println(vals2)
}

在代码示例中,我们定义了一个数组并将该数组赋给一个新变量。通过第二个变量进行的更改不会影响原始数组。

$ go run main.go
[1 2 3 4 5 6]
[11 22 3 4 5 6]

原始数组未更改。

多维数组

我们可以在 Go 中创建多维数组。我们需要额外的方括号和花括号对来表示额外的数组维度。

main.go
package main

import (
    "fmt"
    "math/rand"
)

func main() {

    a := [2][2]int{

        {1, 2},
        {3, 4}, // the trailing comma is mandatory
    }

    fmt.Println(a)

    var b [2][2]int

    for i := 0; i < 2; i++ {
        for j := 0; j < 2; j++ {
            b[i][j] = rand.Intn(10)
        }
    }

    fmt.Println(b)
}

我们使用整数二维数组。

a := [2][2]int{

    {1, 2},
    {3, 4}, // the trailing comma is mandatory
}

fmt.Println(a)

外部数组中有两个嵌套数组。

var b [2][2]int

for i := 0; i < 2; i++ {
    for j := 0; j < 2; j++ {
        b[i][j] = rand.Intn(10)
    }
}

fmt.Println(b)

在第二种情况下,数组被初始化为随机值。我们使用两个 for 循环。

$ go run main.go
[[1 2] [3 4]]
[[9 4] [1 3]]

在下面的示例中,我们创建了一个三维数组。

main.go
package main

import "fmt"

func main() {

    a := [3][2][2]int{
        { {1, 2}, {3, 4} },
        { {5, 6}, {7, 8} },
        { {9, 10}, {11, 12} },
    }

    fmt.Println(a)
    fmt.Println(a[2][1][0])
}

我们需要三对 []{} 括号。

部分赋值

数组可以部分赋值。

main.go
package main

import "fmt"

func main() {

    var a [5]int = [5]int{10, 20, 30}

    fmt.Println(a)
}

数组的类型和大小必须匹配。没有值的元素将被初始化为零。

$ go run main.go 
[10 20 30 0 0]

最后两个元素被初始化为 0。

来源

Go 数组类型 - 规格

在本文中,我们展示了 Golang 中的数组用法。

作者

我叫 Jan Bodnar,是一名充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程