Go语言需依赖第三方库操作Excel,最成熟的是纯Go实现的excelize,支持.xlsx格式、无需Office环境,具备高写入性能与稳定性。

Go 语言本身不内置 Excel 支持,必须依赖第三方库;最成熟、最常用的是 excelize,它纯 Go 实现、无需 Office 环境、支持 .xlsx(不支持 .xls),写入性能和稳定性都经过大量生产验证。
用 excelize 创建并写入新 Excel 文件
这是最常见场景:从零生成一个 .xlsx 文件,填入数据。注意不是“追加”,而是新建工作簿后写入指定单元格或区域。
- 先安装:
go get github.com/xuri/excelize/v2(v2 是当前主力版本) - 创建新文件只需
f := excelize.NewFile(),它默认带一个名为Sheet1的工作表 - 写单个单元格用
f.SetCellValue("Sheet1", "A1", "Hello")—— 行列是字符串格式("B3"),不是数字索引 - 写一整行/列可用
f.SetSheetRow()或f.SetSheetCol(),传入切片(如[]interface{}{"Name", "Age", "City"}) - 务必调用
f.SaveAs("output.xlsx")才真正落盘;若只调用f.Close()而没保存,文件不会生成
向已有 Excel 文件追加数据(非覆盖)
很多人误以为 OpenFile 后直接 SetCellValue 就是“追加”,其实只是修改原位置。真要追加(比如在最后一行后面加新记录),得先读出当前最大行号。
- 用
f, err := excelize.OpenFile("data.xlsx")打开现有文件 - 获取某列最后一行:
rows, _ := f.GetSheetRows("Sheet1")→ 行数 =len(rows);或更准一点:maxRow, _ := f.GetSheetRow("Sheet1", "A")不可靠,推荐用f.GetSheetMap()+f.GetSheetRow()组合判断非空行 - 计算目标行号(比如最后一行+1),再写入:
f.SetCellValue("Sheet1", fmt.Sprintf("A%d", lastRow+1), "New Data") - 如果要插入整行(而非覆盖),用
f.InsertRow("Sheet1", lastRow+1),再写值;否则旧内容会被顶掉
写入时中文乱码或样式丢失?检查这几点
excelize 默认使用 UTF-8,一般不会乱码;但如果你看到方块字或空格错位,大概率是字体或单元格格式问题,不是编码问题。
立即学习“go语言免费学习笔记(深入)”;
- Excel 单元格默认字体是 Calibri,不支持中文显示全——需手动设置中文字体:
styleID, _ := f.NewStyle(&excelize.Style{Font: &excelize.Font{Family: "微软雅黑", Size: 11}}),再用f.SetCellStyle("Sheet1", "A1", "A1", styleID) - 日期写入别直接塞
time.Now(),会变成浮点数(Excel 底层日期序列)。要用f.SetCellDateTime("Sheet1", "B2", time.Now(), "yyyy-mm-dd hh:mm:ss") - 数值型字段如果被写成字符串(比如
"123"而非123),Excel 会当文本处理,求和/排序失效。确保传int/float64类型值,而非fmt.Sprint()结果 - 大文件写入(>10 万行)建议关闭自动计算:
f.SetCalculation(&excelize.Calculation{CalcMode: "manual"}),避免卡顿
为什么不用 tealeg/xlsx 或 go-excel?
这两个库曾经有人用,但现在基本不推荐:
-
tealeg/xlsx已归档(Archived),不再维护,对 Excel 2016+ 新特性兼容差,写入大文件易 OOM -
go-excel功能极简,连合并单元格、样式、日期支持都不完整,且作者已停更两年 -
excelize是 CNCF 孵化项目,有完整测试覆盖率,支持条件格式、图表、数据验证、密码保护等高级功能,文档和示例齐全(官方 GitHub 有 50+ examples)
如果你的场景涉及公式、模板填充、多 sheet 关联或导出给财务系统用,excelize 的 f.SetCellFormula() 和 f.CloneSheet() 是绕不开的刚需;别为了省一行代码去碰边缘库。


















