tealeg/xlsx 不再推荐用于新项目,因其已归档、不维护、不支持现代 Excel 特性且 Save 时易静默丢数据;推荐改用活跃的 qax-os/excelize,需流式读 CSV 并手动解析类型后写入。

为什么 tealeg/xlsx 不再推荐用于新项目
它已归档(archived),不再维护,且不支持 Excel 的现代特性(如公式、条件格式、合并单元格的完整语义),更关键的是——Save 时容易静默丢数据,尤其在写入大文件或含特殊字符的字段时。Go 官方生态里目前更稳妥的选择是 qax-os/excelize,它活跃、文档全、兼容 .xlsx 规范严格。
excelize 写 CSV 到 Excel 的最小可行流程
核心不是“转换”,而是“逐行读 CSV + 逐行写 Sheet”。别指望一行命令搞定,CSV 没有类型/样式信息,Excel 里得手动控制列宽、日期格式、数字精度等。
- 用
encoding/csv打开 CSV 文件,csv.NewReader配合ReadAll或流式Read(大文件必须流式,否则内存爆) - 新建
excelize.File,用NewFile;调用SetSheetRow或SetCellValue写数据——注意:行列索引从 1 开始,不是 0 - 字符串字段若以
=、+、-开头,Excel 会误判为公式,必须前置单引号',可用strconv.Quote或手动处理 - 写完务必调用
SaveAs("out.xlsx"),漏掉这步等于白干
日期和数字字段写入 Excel 的坑
CSV 里的 "2024-03-15" 是纯文本,excelize 不会自动识别成日期类型。直接 SetCellValue 进去,Excel 里显示为左对齐文本,无法排序或参与计算。
- 日期要先解析:用
time.Parse("2006-01-02", s)得到time.Time,再用f.SetCellDateTime写入 - 数字同理:CSV 字段可能是
"123.45000",直接写字符串会当文本;应strconv.ParseFloat后用SetCellFloat - 如果原始 CSV 没明确类型标记,就得靠字段名或正则启发式判断(比如列名含
"date"或"price"),这部分逻辑必须自己补
性能与内存:10 万行 CSV 怎么不 OOM
ReadAll 会把全部 CSV 加载进内存,10 万行 × 10 列 ≈ 100MB+,Go 程序可能卡顿甚至被系统 kill。真实场景必须流式处理。
立即学习“go语言免费学习笔记(深入)”;
- 用
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read()循环读 - 每读一行,立刻
SetSheetRow写入对应行,避免缓存整张表 - 写完后可选调用
f.SetActiveSheet和f.AutoColWidth(但后者对大表很慢,建议跳过) - 最终
SaveAs前,f对象本身只占几 MB 内存,压力在磁盘 IO
excelize)、绕开自动类型推断(自己 parse 再写)。其它都是围绕这两件事填坑。










