
本文详解 Go 语言中计算方阵主对角线(左上→右下)与副对角线(右上→左下)元素和之差的完整实现,重点解决因未初始化内层切片导致的 index out of range panic,并提供健壮、可读性强的标准解法。
本文详解 go 语言中计算方阵主对角线(左上→右下)与副对角线(右上→左下)元素和之差的完整实现,重点解决因未初始化内层切片导致的 `index out of range` panic,并提供健壮、可读性强的标准解法。
在 Go 中处理二维数组(实际为“切片的切片”)时,必须显式初始化每一层结构。原代码中仅调用 make([][]int, n) 创建了长度为 n 的外层切片,但其每个元素(类型为 []int)默认为 nil,尚未分配内存空间。因此当执行 s[i][j] 时,由于 s[i] 是 nil 切片,任何索引访问都会触发 panic: runtime error: index out of range。
正确的做法是:先初始化外层切片,再逐行初始化内层切片。此外,输入逻辑也需修正——原代码使用 fmt.Scanf("%d %d", &s[i][j]) 试图一次读取两个整数,但每行实际应输入 n 个整数(或按行列逐个输入),且格式符与参数数量不匹配,易引发扫描错误。
以下是修复后的完整、健壮实现:
package main
import "fmt"
func main() {
var n int
fmt.Scan(&n)
// 创建 n x n 的二维切片:先分配外层,再逐行分配内层
s := make([][]int, n)
for i := 0; i < n; i++ {
s[i] = make([]int, n) // ✅ 关键:初始化第 i 行
for j := 0; j < n; j++ {
fmt.Scan(&s[i][j]) // 逐个读取,更安全可靠
}
}
var primarySum, secondarySum int
for i := 0; i < n; i++ {
primarySum += s[i][i] // 主对角线:行索引 == 列索引
secondarySum += s[i][n-1-i] // 副对角线:行索引 + 列索引 == n-1
}
fmt.Println(primarySum - secondarySum)
}关键要点说明:
- ✅ 双重初始化不可省略:make([][]int, n) 仅创建外层骨架;必须通过 s[i] = make([]int, n) 为每一行分配实际存储空间。
- ✅ 输入方式优化:使用 fmt.Scan(&s[i][j]) 逐个读取,避免格式符误用;若需支持空格分隔的单行输入(如 "1 2 3"),可改用 fmt.Sscanf 或 strings.Fields 配合 strconv.Atoi。
- ✅ 对角线索引简化:副对角线列索引直接用 n-1-i,比 if i+j == n-1 更高效,且无需嵌套循环——将时间复杂度从 O(n²) 降至 O(n)。
- ⚠️ 边界注意:本解法假设输入为合法 n×n 方阵;生产环境建议添加 n > 0 校验及输入错误处理(如 fmt.Scan 返回值检查)。
运行示例:
输入:
3 11 2 4 4 5 6 10 8 -12
输出:
15
(主对角线和:11 + 5 + (-12) = 4;副对角线和:4 + 5 + 10 = 19;差值:4 − 19 = −15 → 绝对值非必需,按题意输出代数差)
掌握切片的分层初始化机制,是 Go 中安全操作多维数据结构的基础。

















