excelize 是 go 中读写 excel 的稳妥选择,因其原生支持 .xlsx、精确控制样式公式图表、流式写入避免 oom,且持续维护;而 tealeg/xlsx 已停更,功能弱且内存占用高。

用 excelize 读写 Excel 在 Go 里是稳妥选择,但直接照抄文档容易在中文乱码、样式丢失、大文件卡顿上栽跟头。
为什么 excelize 比 tealeg/xlsx 更适合生产环境
它原生支持 .xlsx(不依赖外部程序),能精确控制单元格样式、公式、图表、条件格式;而老库 tealeg/xlsx 已停止维护,对合并单元格、日期类型、自定义数字格式支持极弱。更重要的是,excelize 的内存模型允许流式写入——这点在导出万行报表时决定成败。
- 写入 10 万行数据时,
excelize可配合f.WriteTo直接写入io.Writer(如http.ResponseWriter),避免全量驻留内存 -
tealeg/xlsx必须调用f.Save才生成完整文件,中间所有 Sheet 都常驻内存 -
excelize默认启用 UTF-8,但若从旧系统读取含 BOM 的 CSV 再写入 Excel,需手动调用strconv.Unquote或bytes.TrimPrefix清洗 BOM,否则首列显示怪字符
f.SetCellValue 写中文却显示方块?检查这三处
不是字体问题,大概率是编码或单元格格式没设对。Excel 本身不存“字体”,只存“格式代码”和“字符串原始字节”,excelize 默认按 UTF-8 解析,但若模板 Excel 是用 Excel 2003 保存的旧格式(或从 Windows 记事本另存为 ANSI),就可能混入 GBK 字节流。
- 确认源数据是纯 UTF-8 字符串:用
utf8.ValidString(s)检查,非 true 就别往 Excel 塞 - 写入前显式设置单元格格式:
f.SetCellStyle("Sheet1", "A1", "A1", styleID),其中styleID来自f.NewStyle(&excelize.Style{Font: &excelize.Font{Family: "微软雅黑"}}) - 避免用
f.SetRowHeight粗暴调高行高来“撑开”中文——这会让自动换行失效;应改用f.SetColWidth+f.SetCellStyle中开启WrapText: true
读取 Excel 时 f.GetCellValue 返回空字符串?先看类型
GetCellValue 只返回“渲染后”的文本,对公式、日期、布尔值会做隐式转换,极易误判。比如 Excel 里输入 2024/5/20,实际存的是浮点数 45432(Excel 日期纪元偏移),GetCellValue 虽能转成 "2024-05-20",但若单元格格式被手动设为“常规”,它就真返回 "45432"。
- 优先用
f.GetCellType判断类型:cellType == excelize.CellTypeFormula或cellType == excelize.CellTypeDate - 日期值务必用
f.GetCellFloat拿原始浮点数,再传给time.DateFromExcel转时间 - 公式结果为空?检查是否启用了公式计算:
f.Calculation.On = true并调用f.Calculate(),否则默认只读静态值
导出大文件(>5MB)变慢甚至 OOM?关掉自动样式缓存
excelize 默认为每个唯一样式新建 ID 并缓存,万行数据若每行设不同背景色,会生成上万个样式对象,GC 压力陡增。这不是 bug,是设计权衡。
- 复用样式:用
f.NewStyle创建一次,存为全局变量或池化复用,别每次SetCellStyle都新建 - 关闭样式哈希缓存(v1.4+):
f.SetSheetProps("Sheet1", &excelize.SheetProps{EnableFormatConditions: false}),可降内存 30%+ - 写入完毕立刻调用
f.Close(),它会强制 flush 临时 ZIP 流并释放底层zip.Writer,不关的话文件句柄和缓冲区一直挂着
最常被跳过的其实是 f.AutoFilter 和 f.SetPivotTable 的区域校验——参数里给错行列范围,运行时不报错,打开 Excel 却提示“发现不可读内容”,修复只能靠重开文件手动删透视表。这类操作建议加一层 if !f.GetSheetMap()["Sheet1"].IsValidRange("A1:D100") { ... } 防御。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











