用 csv.Writer 写入 CSV 文件最直接:它自动处理分隔、引号转义和换行,需包装 io.Writer(如 *os.File),先写表头(可选),每行传 []string,最后必须调用 Flush()。

用 csv.Writer 写入 CSV 文件是最直接的方式
Go 标准库的 encoding/csv 包提供了 csv.Writer 类型,它封装了写入逻辑,自动处理字段分隔、引号转义、换行符等细节。不要自己拼接字符串或手动加双引号——CSV 格式有明确规范(比如字段含逗号、换行或双引号时必须被包裹并转义),csv.Writer 会正确处理这些。
关键点:
-
csv.Writer必须包装一个io.Writer,最常用的是*os.File - 写入前建议调用
w.Write([]string{...})写表头(可选但推荐) - 每行数据必须是
[]string,即使数字也要先转成字符串(Go 不做隐式类型转换) - 写完后必须调用
w.Flush(),否则缓冲区内容可能未落盘
写入时字段含特殊字符怎么办
csv.Writer 默认使用英文逗号作为分隔符,双引号作为引用符,并自动启用引号策略:csv.Writer 会在以下情况自动给字段加双引号:
- 字段中包含分隔符(如
,) - 字段中包含换行符(
\n或\r\n) - 字段以双引号开头,或本身含双引号(此时内部双引号会被转义为两个双引号)
你不需要手动判断是否加引号,也不需要提前替换 " → "" —— csv.Writer 全部代劳。
立即学习“go语言免费学习笔记(深入)”;
例如,写入 []string{"Alice", "Sales, Dept", "She said: \"Hi\"."} 会生成:
"Alice","Sales, Dept","She said: ""Hi""."
如何自定义分隔符或禁用引号
csv.Writer 支持有限定制:
- 修改分隔符:设置
w.Comma = '\t'即可生成 TSV(注意必须是 ASCII 字符) - 禁用自动引号:设置
w.UseCRLF = false只影响换行符风格(Windows vs Unix),不影响引号逻辑 - 无法完全禁用引号——标准
csv.Writer没有QuoteNone选项;如果真需要无引号输出(且确认数据绝对安全),得自己实现写入逻辑,但不推荐
若需制表符分隔 + 自动引号,只需:
w := csv.NewWriter(f)
w.Comma = '\t'
w.Write([]string{"name", "desc"})
w.Write([]string{"Bob", "Engineer\tL3"})
w.Flush()
常见错误:文件没内容、中文乱码、panic
这些问题通常源于忽略底层 I/O 细节:
-
文件为空:忘记调用
w.Flush()或f.Close(),导致缓冲区未写入磁盘 -
中文显示为乱码(如 ):CSV 本身不定义编码,但 Excel 默认按系统 ANSI(如 Windows-1252)打开;保存为 UTF-8 并在文件开头写入 BOM(
\xEF\xBB\xBF)可让 Excel 正确识别 -
panic: runtime error: invalid memory address:对已关闭的
*os.File调用w.Write(),或传入nil的io.Writer -
写入后文件被锁/无法删除:没调用
f.Close(),尤其在 Windows 上容易触发
稳妥写法应确保资源释放:
f, err := os.Create("data.csv")
if err != nil {
log.Fatal(err)
}
defer f.Close() // 关键
w := csv.NewWriter(f)
defer w.Flush() // 关键
w.Write([]string{"姓名", "城市"})
w.Write([]string{"张三", "北京"})
// ...
写 CSV 看似简单,真正容易出问题的是缓冲控制、编码兼容性和资源生命周期——尤其是和 Excel 交互时,BOM 和换行符风格几乎每次都会踩一次。










