导出CSV时中文乱码需手动写入UTF-8 BOM(\xef\xbb\xbf),换行符崩格式须由csv.Writer自动转义——禁用字符串拼接,统一调w.Write([]string{}),并显式Flush()防缓冲丢失。

用 encoding/csv 导出 CSV 时,中文乱码、换行符崩格式怎么办
Go 原生 encoding/csv 不处理 BOM,也不自动转义换行符和双引号,直接写入中文会显示为乱码(尤其在 Excel 中打开),含换行的字段还会导致行数错乱。
- 导出前手动写入 UTF-8 BOM:
w.Write([]byte("\xef\xbb\xbf"))(仅需一次,在csv.NewWriter底层io.Writer上操作) - 字段值含
\n、\r或双引号时,必须由csv.Writer自动包裹引号 —— 别自己拼字符串,否则Write会报illegal char - 避免用
fmt.Sprintf拼 CSV 行,一律走w.Write([]string{...}),让 writer 负责转义 - 导出大文件时调用
w.Flush()防止缓冲区阻塞,但别每行都 flush,性能差
用 tealeg/xlsx 或 qax912/excelize 读 Excel,为什么空单元格读出来是 nil 或 0
Excel 的“空”分语义:真空白、空字符串、零值、公式结果为空 —— 不同库默认行为不同。比如 tealeg/xlsx 把未设置值的单元格返回 nil,而 excelize 默认返回 "" 或 0,取决于类型推断。
- 读取前先用
sheet.GetCell(x, y)判断是否== nil(xlsx)或检查cell.GetCellValue() == "" && cell.NumValue == 0(excelize) -
excelize更推荐:它支持.xlsx和流式读写,且GetCellValue对空字符串、NULL、空公式统一返回"",可设f.SetSheetUnzipReader提升大表性能 - 别依赖
Row.Cells长度判断列数,Excel 行可能稀疏;用Row.GetCellCount()(excelize)或遍历Row.Cells并跳过nil(xlsx)
封装通用导入函数时,如何统一处理 CSV/Excel 不同结构的数据
CSV 是纯二维表,Excel 可能多 Sheet、有标题行偏移、首行不一定是字段名 —— 强行用同一结构体接收必然出错。
- 定义输入参数结构体,包含
SheetName string(Excel 用)、HeaderRow int(默认 0)、HasHeader bool(决定是否跳过首行) - 内部先用
filepath.Ext(path)分发:CSV 走encoding/csv+bufio.Reader,Excel 走excelize.OpenFile+f.GetSheetMap() - 读到原始数据后,统一转成
[]map[string]interface{}:键为标题行内容(自动去重+加序号后缀),值按列类型转换(strconv.Atoi/time.Parse等) - 错误要区分层级:文件打开失败(底层 error)、Sheet 不存在(业务 error)、某行字段数不匹配(警告并记录行号)
导出 Excel 时合并单元格、设置样式,为什么生成的文件 Excel 打不开
合并单元格和样式必须在写入数据**之后**、保存文件**之前**调用,且坐标必须合法(如 A1:B1 合法,A1:A0 或跨 Sheet 合并不行)。Excel 会校验 XML 结构,非法操作导致文件损坏。
立即学习“go语言免费学习笔记(深入)”;
- 用
excelize:先f.SetCellValue写完所有数据,再f.MergeCell("Sheet1", "A1", "B1"),最后f.SaveAs - 样式必须先
f.NewStyle创建 ID,再f.SetCellStyle("Sheet1", "A1", "A1", styleID);重复调用NewStyle会泄漏 style ID - 避免对空单元格设样式(如
SetCellStyle("A1000", "A1000")但该格没写过值),Excel 可能拒绝解析 - 导出后用
zip -T file.xlsx检查 ZIP 完整性,再用 Excel 手动打开看提示 —— 多数“打不开”问题其实是 XML 标签未闭合或命名空间错位
ValidateSheet 检查合并范围是否重叠、样式是否绑定到已写单元格、日期格式是否符合 excelize 要求的数字戳。


















