导出csv中文乱码需加utf-8 bom;导入时须解析header映射字段索引,避免顺序依赖;大数据量应流式处理+批量插入;导出excel须用excelize库,禁用saveas改用writeto流式响应。

导出用户数据到 CSV 时中文乱码怎么办
Go 默认生成的 CSV 文件没有 BOM,Excel 打开会把 UTF-8 当作 ANSI 解析,导致中文全乱。这不是编码错了,是 Excel 自作聪明。
- 导出前在
csv.Writer写入的第一行之前,手动写入 UTF-8 BOM:w.Write([]byte("\xEF\xBB\xBF")) - 不要用
os.Create,改用os.OpenFile并加os.O_CREATE | os.O_WRONLY | os.O_TRUNC标志,确保文件可重写 - 字段含逗号、换行或双引号时,
csv.Writer会自动转义,但必须调用w.Flush()才能真正写入磁盘,否则文件可能为空
用 encoding/csv 读 CSV 导入用户时字段顺序错乱
CSV 没有 schema,靠列顺序映射结构体字段。一旦 Excel 用户拖动列、导出时字段顺序变动,csv.Reader 就会把邮箱填进昵称字段。
- 导入前先读第一行(
r.Read()),拿到 header 列表,和预期字段名比对,比如检查是否存在"email"、"nickname" - 建一个字段名 → 列索引的 map:
colIndex := map[string]int{"email": -1, "nickname": -1},遍历 header 填充它 - 后续每行用
row[colIndex["email"]]取值,不依赖固定位置;缺失关键字段(如 email)直接跳过该行,记日志 - 别信前端传来的“字段顺序”,服务端必须自己解析 header
导入大量用户时内存暴涨甚至 OOM
一次性 ReadAll 整个 CSV 文件到内存,几万行就吃掉几百 MB,尤其字段里还有 base64 头像。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
- 永远用流式处理:循环调用
r.Read(),每读一行解析、校验、入库(或发到 channel 异步处理) - 数据库插入别用单条
INSERT,攒够 100–500 行用INSERT INTO ... VALUES (...), (...)批量写入 - 如果用 GORM,关掉
Save的 hook 和日志:db.Session(&gorm.Session{SkipHooks: true, Logger: logger.Default.LogMode(logger.Silent)}) - 注意
csv.Reader的底层bufio.Reader缓冲区大小,默认 4KB,大字段多时设为 64KB 避免频繁系统调用
导出用户到 Excel(.xlsx)而不是 CSV 怎么办
encoding/csv 不支持 Excel 格式,硬塞 .xlsx 后缀只是骗文件管理器,Excel 打开会报错“文件格式损坏”。
- 真要 xlsx,用
github.com/xuri/excelize/v2,它不依赖 Office 环境,纯 Go 实现 - 创建 sheet 后先写 header 行,再逐行
f.SetRow("Sheet1", i, row),注意行号从 1 开始 - 导出前调用
f.SetColWidth("Sheet1", "A", "Z", 20)防止中文被截断;日期字段用f.SetCellDateTime而不是字符串,否则 Excel 无法识别为时间 - 别用
f.SaveAs直接写磁盘——导出接口应返回io.Reader,用f.WriteTo(w)流式响应,避免临时文件和内存拷贝
最麻烦的从来不是读写文件,而是用户上传的 CSV 字段名拼错、空格多一个、首行被当数据、Excel 自动转数字(比如把 00123 变成 123)。这些没法靠库解决,得在解析层加显式校验和容错提示。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










