go标准库encoding/csv安全读写需关注flush()、bom和文件指针:writer必须显式flush()防丢行;导出中文须手动写utf-8 bom(\xef\xbb\xbf)适配excel;reader前需seek(0,0)并trimprefix去bom;大文件须流式处理,禁用readall/writeall。

Go 标准库 encoding/csv 能安全读写 CSV,但直接用容易丢数据、乱码、错行——核心问题不是“会不会”,而是“Flush()调没调”“BOM加没加”“文件指针在不在开头”。
csv.Writer 必须显式 Flush(),否则最后一行大概率丢失
标准库的 csv.Writer 底层用 bufio.Writer 缓冲,默认 4KB。不调 Flush(),数据就卡在内存里,程序退出时直接丢弃。
- HTTP 导出场景下,没
Flush()会导致浏览器只收到部分响应,甚至超时中断 -
defer w.Flush()不可靠:中间 panic 时 defer 可能不执行 -
WriteAll()内部会 flush,但只覆盖本次调用的数据;后续再Write()还得自己 flush - 检查是否写成功不能只看
Write()返回值,还要在Flush()后查w.Error(),它汇总了整个缓冲期内所有失败
写入中文到 Excel,必须手动加 UTF-8 BOM
Windows 版 Excel 默认用 GBK 解析无 BOM 的 UTF-8 CSV,中文全变乱码。这不是 Go 的 bug,是 Excel 的老习惯。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 加 BOM 只需在写任何数据前,对底层
*os.File或bytes.Buffer执行:file.Write([]byte("\xef\xbb\xbf")) - 别用
string拼接或fmt.Fprintln写 BOM —— 它们可能触发额外编码转换 - macOS Numbers 和 LibreOffice 通常不依赖 BOM,但加了也无害;不加 BOM 则 Windows Excel 基本不可用
- 不要尝试把字符串转 GBK 写入:Go 标准库不支持,第三方库如
golang.org/x/text/encoding/charmap可用,但没必要绕路
csv.NewReader 读不到数据?先查文件指针和 BOM
常见现象是 reader.Read() 立即返回 io.EOF 或空切片,实际文件明明有内容。90% 是这两个原因:
- 文件指针已偏移:比如之前调过
file.Stat()、io.ReadAll(file)或其他读操作,*os.File的内部 offset 不在开头。解决方法:创建 reader 前加file.Seek(0, 0) - UTF-8 BOM 被当非法字符:Windows 记事本保存的 CSV 开头常含
\xef\xbb\xbf,csv.NewReader会报invalid UTF-8或字段解析失败。解决方法:用bytes.TrimPrefix剥掉 BOM,再包进io.MultiReader传给 reader - 别用
strings.ReplaceAll处理 BOM —— 它会全局替换,可能误删字段内真实出现的\ufeff - 如果源文件是 GBK/GB18030,必须用
golang.org/x/text/encoding/charmap.GB18030.NewDecoder().Reader(file)包一层,再传给csv.NewReader
大文件读写必须流式处理,ReadAll() 和 WriteAll() 是内存炸弹
ReadAll() 把整个 CSV 加载进内存,100MB 文件实际吃掉 400MB+ RAM 很常见;WriteAll() 虽不加载,但若传入超大二维切片,也会导致栈/堆压力激增。
- 读大文件:用
for { record, err := reader.Read() }循环,每行处理完立刻释放引用,别 accumulate 到[][]string - 写大文件:批量写(比如每 1000 行)后主动
Flush(),避免缓冲区撑爆;创建 writer 时可传自定义bufio.NewWriterSize(file, 64*1024)控制缓冲大小 - 别用
strings.Builder先攒全部内容再写 —— 字符串拼接内存占用线性增长,百万行轻松几百 MB - 数据库导出场景:边
rows.Next()边w.Write(),别先把整张表Scan到内存
最易被忽略的其实是「字段语义」:CSV 本身没有 schema,""、"NULL"、"\N"、空白字段在标准库眼里全是字符串,业务层必须自己定义规则并统一处理。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










