excelize 是一个非常强大且广泛使用的库,可以让我们轻松创建、读取和修改 .xlsx 文件。本文将带你逐行分析一个完整的 Go 程序,从 package main 到保存文件,深入理解每一行代码背后的原理和最佳实践。
一、代码总览
先来看完整的程序:

这个程序的功能非常简单:创建一个新的 Excel 文件,新建一个名为 Sheet2 的工作表,在 Sheet2 的 A2 单元格写入 "Hello Goland.",在默认的 Sheet1 的 B2 单元格写入数字 100,最后保存为 Book2.xlsx。
虽然代码量不大,但里面包含了 Go 语言中许多重要的基础概念和编程范式。接下来我们逐一拆解。
二、包声明与导入
2.1 package main – 可执行程序的标识
在 Go 中,每个源文件都以 package 声明开头。package main 是一个特殊的包,它告诉 Go 编译器:“这个包要编译成一个可执行程序(而不是一个库)”。当你运行 go build 时,会生成一个 .exe 文件(在 Windows 上)或可执行二进制文件(Linux/macOS)。
如果包名不是 main(比如 package math),则会被编译成库文件,供其他程序调用,不会生成可执行文件。
隐含规则:package main 必须包含一个名为 main() 的函数,这是程序的入口点。
2.2 导入依赖

fmt是 Go 标准库中的包,提供格式化输入输出功能,我们用它来打印错误信息和日志。 github.com/xuri/excelize/v2是第三方库 excelize的导入路径。路径中的/v2表示大版本号(Go Modules 的语义化版本控制规则),这样可以兼容不同主版本之间的不兼容变更。
三、main() 函数与程序入口
main() 函数不接受任何参数,也没有返回值。当执行 go run main.go 时,操作系统会调用这个函数,程序从这里开始运行。
四、创建 Excel 文件对象
excelize.NewFile()是 Excelize 库提供的函数,它在内存中创建一个全新的 .xlsx文件对象。此时还没有实际的磁盘文件,所有数据都存储在内存的数据结构中。 f是一个指针( *excelize.File),指向这个文件对象。后续所有操作(如创建工作表、写入单元格、保存)都通过这个指针进行。
知识:Go 中
:=是简短变量声明,它会自动推断类型。
五、defer 与资源释放 – 保证安全的惯用法

这是 Go 中管理资源释放最经典、最安全的模式。我们来拆解:
defer:关键字,用于延迟执行一个函数调用,直到所在函数(这里是 main)返回前一刻才执行。无论函数是正常结束还是发生了panic,defer都会被执行。- 匿名函数:
func() { ... }()定义了一个没有名字的函数,并立即将其声明为延迟调用。之所以用匿名函数,是为了可以在里面执行多条语句(这里做了错误处理)。 f.Close():释放 excelize.File占用的系统资源(如文件句柄、内存缓冲区)。即使后续SaveAs失败或程序中途退出,这个Close()也一定会被调用。- 错误检查:
Close()也可能失败(比如磁盘已满),我们将错误打印出来,帮助调试。
为什么要这样做?如果不主动调用 Close(),程序在大量创建 Excel 文件时可能会耗尽系统资源,造成文件句柄泄漏,最终导致程序崩溃。而 defer 保证了资源释放的确定性,无论业务逻辑多复杂,资源都能被回收。
注意:如果有多个
defer语句,它们按 后进先出(LIFO) 的顺序执行,类似于栈。这在需要对称操作(如加锁/解锁)时非常有用。
六、创建新工作表

f.NewSheet("Sheet2")在当前文件中创建一个名为 Sheet2的新工作表(Excel 底部会多出一个标签页)。返回值: index:新工作表的索引(整数,从 0 开始)。Excel 内部按顺序编号, Sheet1默认索引为 0。err:如果创建失败(例如名称重复),会返回一个非 nil的错误。
Go 的错误处理哲学
Go 没有 try/catch 异常机制,而是通过显式返回错误值的方式。
必须主动检查 err,否则程序可能在一个不可知的状态下继续运行,导致更难追踪的问题。在示例中,我们打印错误并直接 return 退出程序。
七、写入单元格数据

SetCellValue(sheet, cell, value)将数据写入指定工作表的单元格。sheet:字符串,工作表名称。 cell:单元格坐标,例如 "A2"(列字母 + 行号)。value:要写入的数据,可以是 string、int、float64、bool等类型,Excelize 会自动处理类型转换。- 注意
Sheet1是 Excel 默认创建的工作表,无需额外调用NewSheet。 - 这里我们忽略了
SetCellValue返回的错误(实际上它有返回值error)。在示例中这样做是为了简洁,但生产环境建议务必处理错误
八、设置活动工作表

一个 Excel 文件可以有多个工作表,但打开时只显示一个。 SetActiveSheet(index)决定打开文件后默认显示哪个工作表。 这里的 index是之前NewSheet返回的索引,所以打开Book2.xlsx时会直接显示Sheet2。
九、保存文件

f.SaveAs("Book2.xlsx")将内存中的 Excel 数据结构写入磁盘文件。 参数是文件路径(相对或绝对均可)。这里使用相对路径,保存到当前工作目录。 同样,我们检查了错误并打印,但未退出程序(可以根据需求决定是否 return)。如果保存失败(如权限不足、磁盘满),错误信息会输出到控制台。
十、程序执行流程图
为了更直观地理解代码的执行顺序,这里给出一个流程图:

十一、关键知识点回顾
package main | package main | |
import | import "fmt" | |
func main() | func main() { ... } | |
:= | f:=excelize.NewFile() | |
defer | defer f.Close() | |
if err != nil | if err != nil { return } | |
f.SetCellValue(...) | ||
f.Close() |
参考资料:
Excelize 官方文档 Go 语言规范 – defer 语句
夜雨聆风