用 csv.Writer 写入带表头的 CSV 文件最稳妥:先调用 Write 写入表头切片,再逐行写数据,最后必须调用 Flush;需手动写 UTF-8 BOM 防 Excel 乱码,大文件应调大缓冲区并流式写入。

用 csv.Writer 写入带表头的 CSV 文件最稳妥
Go 标准库的 encoding/csv 是处理结构化文本最可靠的选择,尤其适合带表头的导出场景。它自动处理字段中的逗号、换行、双引号转义,避免手写拼接引发的解析错误。
关键点在于:表头不是“额外写一行”,而是和数据一起由 Write 方法统一处理;必须在写数据前调用一次 Write 写入表头切片,否则后续每行数据会被当成普通记录,表头就丢了。
常见错误是先 fmt.Fprintln 手动写表头——这会导致 CSV 解析器无法识别列名,且破坏字段转义逻辑。
- 表头用
[]string表示,如[]string{"name", "age", "city"} - 每条数据也必须是
[]string,即使数值字段也要strconv.Itoa转字符串 - 写完所有行后务必调用
w.Flush(),否则最后一行可能不落盘
file, _ := os.Create("users.csv")
w := csv.NewWriter(file)
defer file.Close()
// 先写表头
w.Write([]string{"name", "age", "city"})
// 再写数据行
w.Write([]string{"Alice", "30", "Beijing"})
w.Write([]string{"Bob", "25", "Shanghai"})
w.Flush() // 必须调用
写入 Excel(.xlsx)需用第三方库,tealeg/xlsx 最轻量
Go 原生不支持 Excel 二进制格式,tealeg/xlsx 是目前维护活跃、API 简洁的首选。它不依赖外部程序,纯 Go 实现,适合服务端批量导出。
立即学习“go语言免费学习笔记(深入)”;
注意:它生成的是 .xlsx(Office 2007+),不支持旧版 .xls;且表头和数据都通过 *xlsx.Row 添加,没有“自动映射字段”机制,需手动控制列顺序。
- 创建新工作簿:
xlsx.NewFile(),再AddSheet - 获取第一行:
sheet.AddRow(),然后对每个单元格调用row.AddCell().SetValue(...) - 数值类型建议用
SetInt或SetFloat,避免字符串存储导致 Excel 识别为文本 - 中文表头无需额外设置编码,
tealeg/xlsx默认 UTF-8
写入带 BOM 的 UTF-8 文本文件,防止 Excel 打开乱码
Windows 上 Excel 默认用系统编码(GBK)打开 CSV,遇到 UTF-8 中文会显示乱码。解决办法是在文件开头写入 UTF-8 BOM(\xEF\xBB\xBF),Excel 就能自动识别。
但 csv.Writer 不负责 BOM,必须在创建 *os.File 后立即写入,且要在创建 csv.Writer 之前完成。
- 不要用
os.OpenFile追加模式(os.O_APPEND),BOM 只能写在开头 - 写 BOM 后再传给
csv.NewWriter,writer 会接着写后面的内容 - 如果用
ioutil.WriteFile或os.WriteFile,需自己拼接 BOM 字节切片
file, _ := os.Create("data.csv")
file.Write([]byte("\xEF\xBB\xBF")) // 写入 BOM
w := csv.NewWriter(file)
w.Write([]string{"姓名", "年龄", "城市"})
w.Write([]string{"张三", "28", "杭州"})
w.Flush()
大文件写入时别用 csv.Writer 缓冲默认值
默认缓冲区大小是 4KB,写入百万行时频繁 flush 会拖慢速度。可调大缓冲区减少系统调用次数,但要注意内存占用。
更关键的是:别把所有数据先存进内存 slice 再循环写——这会吃光内存。应边查数据库边写,或用 channel 流式生成。
- 调整缓冲区:
w := csv.NewWriterSize(file, 64*1024)(64KB) - 每写 1000 行主动
w.Flush(),防内存堆积 - 避免
rows := db.QueryRows(); for _, r := range rows { w.Write(r) }这类全量加载
表头本身极小,但和大量数据混在一起时,最容易被忽略的是 flush 时机和缓冲区配置。


















