excelize是当前go生态中唯一适合生产环境批量导入excel的库,tealeg/xlsx已停更;应显式用getrow从第2行起逐行读取,跳过表头,结合getmergecells处理合并单元格,并对字符串转类型做空格清理、多格式时间解析及错误行精准日志记录。

excelize 是当前 Go 生态中唯一适合生产环境批量导入 Excel 的库,tealeg/xlsx 已停更、不支持流式读、无 .xlsx 兼容性保障。别用 GetSheetRows 一次性加载全部行——它会把空行、合并单元格残留的 "" 全塞进来,且无法跳过表头;真正可控的方式是用 GetRow 显式从第 2 行起逐行读。
以下直击高频卡点,按实操路径组织:
如何跳过 Excel 表头并安全读取数据行
Excel 行号从 1 开始,GetSheetRows("Sheet1") 返回的是从第 1 行开始的二维切片,第一项就是表头。但很多人误以为“库自动跳过”,结果把“工单号”“创建时间”当数据插进数据库。
- 显式指定起始行:用
f.GetSheetMap()["Sheet1"]获取总行数,再从row := 2循环到末尾 - 每行调
f.GetRow("Sheet1", row),返回[]string按列顺序排列,和 Excel 界面一致 - 遇到空行(
len(cells) == 0)或读取出错直接continue,避免 panic - 合并单元格会导致某列返回
"",需提前调f.GetMergeCells()获取范围,并手动补值
字段类型转换怎么防 panic
Excel 所有单元格内容本质都是字符串,strconv.Atoi 遇到空格、"N/A"、"—" 或纯空字符串会直接 panic,而数据库字段又要求非空或特定类型。
- 所有字符串转数字前必须
strings.TrimSpace(s),否则" 123 "就失败 - 空值策略要明确:是设为
nil(对应 SQL NULL)、零值(0/time.Time{}),还是业务兜底值(如"未知") - 时间解析不能只试一种 layout:
"2006-01-02"、"2006/01/02"、"2006-01-02 15:04"应组成切片循环尝试 - 布尔字段别信 Excel 里写的 “是/否”,统一映射为
map[string]bool{"是": true, "否": false, "Y": true, "N": false}
为什么不能用 db.Exec 逐行插入
这不是性能问题,是稳定性灾难:每条 Exec 都触发一次网络 round-trip、一次事务提交、一次 WAL 写入。万级数据下,连接池耗尽、context.DeadlineExceeded、MySQL 的 max_allowed_packet 错误会密集爆发。
- PostgreSQL 用户必须用
pgx.Conn.CopyFrom:它走二进制 COPY 协议,比 Exec 快 5–10 倍,且不经过 SQL 解析层 - MySQL 用户优先启用
LOAD DATA LOCAL INFILE(需服务端开local_infile=ON,驱动加allowLocalInfile=true),否则只能手拼INSERT INTO t VALUES (),(),()...,注意用mysql.Escape转义字符串 - 无论哪种方式,都必须分批:CopyFrom 每次传 1000–5000 行;手拼 SQL 控制单条语句不超过 1MB,避免超包
- 每批必须套独立
tx, _ := db.BeginTx(ctx, nil),出错时tx.Rollback(),成功后tx.Commit()
导入失败时怎么精准定位哪一行哪一列错了
错误信息如 "parse error at line 123" 或 "cannot convert string to int64" 根本不够用——你不知道原始值是什么、上下文是否含隐藏空格、日期格式是否被 Excel 自动改写过。
- 在读取循环内打日志:
log.Printf("line %d: raw=%q, err=%v", row, cells, err),%q会显示带引号的原始字符串,包括空格和换行 - 对关键字段(如 ID、时间)做前置校验:长度超限、含非法字符、为空但数据库不允许 NULL,就提前报错并记录
- 不要等入库才校验:在内存中完成清洗和类型转换后再进 DB 层,否则失败时已部分写入,回滚成本高
- 失败行导出为
error_lines_20260601.csv,保留原始[]string和错误原因,供人工复核
"",也可能返回 nil(取决于 excelize 版本和单元格格式),而“看似空”的合并单元格区域,GetRow 只在首列返回值,其余列为 ""。不检查 GetMergeCells() 并做填充,数据就断层了。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











