Golang中数组的深入理解与使用

Golang中数组的深入理解与使用 我正在尝试理解这里发生了什么。代码的GitHub链接

var twoD [2][3]int
for b := 0; b <2; b++ {
for c := 0; c <3; c++ {
twoD[b][c] = b + c
}
}
fmt.Println("2d:", twoD)

这是基本的设置,它可以正常工作。但是当我将 b <2 改为 b <3 或 b <4 时,会出现:

goroutine 1 [running]:
main.main()
c:/path to file/tut.go:14 +0x39a
exit status 2

所以我想知道为什么会发生这种情况。

另外,如果我在第一个方括号里加上4,变成 [4][3],它会给出4组数组而不是2组。我没有预料到这一点,但好吧。所以有人能解释一下它为什么会这样运作吗?谢谢


更多关于Golang中数组的深入理解与使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

好的,第二部分我完全理解。第一部分稍微复杂些,但我想我明白了。首先,那种写法是正确的还是最优的?我原本以为我创建的是两组数组,一组是[2]int,另一组是[3]int,而不是两组[3]int。现在我理解这部分了,但当我设置twoD[b]时,这是在指定要创建多少组数组吗?这样理解对吗?所以最初是twoD[2],但我设置b<3就导致了问题,对吗?因为twoD[2]不会接受任何大于2的索引值,只能是0和1。

更多关于Golang中数组的深入理解与使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,数组的声明方式为 var identifier [size]type,因此如果将 size 替换为 2,type 替换为 [3]int,你将得到一个由整型数组(每个大小为 3)组成的数组(大小为 2)。在讨论数组时,它们的大小始终是固定的,其类型实际上是大小和数组元素类型的组合。例如,[2]int[3]int 是不同的类型。正如教程所述:

类型 [n]T 是一个包含 nT 类型值的数组。

表达式 var a [10]int 声明了一个变量 a,它是一个包含十个整数的数组。

数组的长度是其类型的一部分,因此数组的大小不能调整。

此外,如前所述,尝试访问超出数组边界的索引处的元素是非法的,并会导致程序崩溃。

var a [10]int

我认为你需要查看数组数据结构的基础知识,以及Go数组。但为了解答你的疑问:

  1. 如果你将条件从 b < 2 改为 b < X,对于任何满足 X > 2 的X值都会失败。这是因为 twoD 的大小是2(它是一个包含2个 [3]int 元素的 [3]int 数组的数组),而Go中的数组是从0开始索引的,现有元素位于位置0和1。因此尝试访问 b[2]b[3] 等将会引发panic,因为你试图读取超出数组大小的范围。

  2. 实际上,你定义 twoD 是一个大小为4的 [3]int 数组的数组,所以4是它包含的元素数量(在这种情况下是数组)。为了更清楚说明,如果你声明 var a [4]int 就是声明一个包含4个整数的数组,var a [4]string 声明一个包含4个字符串的数组,等等。所以在你的例子中,var fourD [4][3]int 声明了一个包含4个 [3]int 数组的数组。

在Golang中,数组是固定长度的数据结构,当访问超出数组边界时会发生运行时panic,这就是你遇到的情况。

问题分析

你的代码定义了一个二维数组:

var twoD [2][3]int  // 2行3列的数组

这个数组的索引范围是:

  • 第一维:0到1(共2个元素)
  • 第二维:0到2(共3个元素)

边界越界错误

当你将 b < 2 改为 b < 3b < 4 时:

for b := 0; b < 3; b++ {  // 错误:b 会取到 0,1,2
    for c := 0; c < 3; c++ {
        twoD[b][c] = b + c  // 当 b=2 时,twoD[2] 超出边界
    }
}

由于数组 twoD 只有2行(索引0和1),访问 twoD[2] 会导致数组越界,触发panic。

数组大小修改

当你将数组声明改为 [4][3]int

var twoD [4][3]int  // 现在有4行3列

数组大小变为:

  • 4行(索引0到3)
  • 3列(索引0到2)

此时循环可以正常执行:

for b := 0; b < 4; b++ {    // b: 0,1,2,3
    for c := 0; c < 3; c++ { // c: 0,1,2
        twoD[b][c] = b + c   // 所有访问都在有效范围内
    }
}

正确的示例

package main

import "fmt"

func main() {
    // 正确声明和使用
    var twoD [2][3]int
    for i := 0; i < 2; i++ {
        for j := 0; j < 3; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d:", twoD) // 输出: 2d: [[0 1 2] [1 2 3]]
    
    // 使用len()函数避免硬编码边界
    var anotherTwoD [4][3]int
    for i := 0; i < len(anotherTwoD); i++ {
        for j := 0; j < len(anotherTwoD[i]); j++ {
            anotherTwoD[i][j] = i * j
        }
    }
    fmt.Println("Another 2d:", anotherTwoD)
}

数组在Go中是值类型,长度是类型的一部分。访问数组时必须在声明的大小范围内,否则会导致运行时panic。

回到顶部