go读csv时需手动处理utf-8 bom、校验utf-8合法性、正确处理io.eof边界、依赖csv.writer自动引号转义,四者缺一不可。

读 CSV 时 encoding/csv 默认不处理 BOM,中文字段乱码怎么办
Go 的 csv.NewReader 不会自动跳过 UTF-8 BOM,如果文件以 \uFEFF 开头,第一列字段名或首行数据前会多出不可见字符,导致 header[0] 看似是 "name",实际是 "\uFEFFname",后续 map 查找失败。
- 读取前先用
ioutil.ReadFile(Go 1.16+ 改用os.ReadFile)加载字节,检查并截掉 BOM:data, _ := os.ReadFile("data.csv") if len(data) >= 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF { data = data[3:] } - 再用
bytes.NewReader(data)包装,传给csv.NewReader,避免在流式读取中反复检测 - 别依赖
strings.TrimSpace清洗字段名——BOM 不是空白符,TrimSpace对它无效
写 CSV 时 WriteAll 报 write error: bad utf-8
错误不是编码问题,而是你传了含非法 UTF-8 字节的字符串,比如从二进制文件误读、C 语言字符串零截断残留、或某些数据库导出字段混入控制字符。Go 的 csv.Writer 在 WriteAll 前不做 UTF-8 校验,但底层 io.WriteString 会在写入时 panic。
- 写入前对每行每字段做轻量校验:
import "unicode/utf8" func isValidUTF8(s string) bool { return utf8.ValidString(s) }遇到false就替换或丢弃,别硬写 - 别用
strings.ToValidUTF8(不存在),Go 没提供自动修复函数;可用strings.ToValidUTF8是 .NET 的,Go 里得自己替换:用bytes.ReplaceAll([]byte(s), []byte{0xFF, 0xFF}, []byte("?"))这类粗暴方式,或引入golang.org/x/text/transform做安全转义 - 注意:MySQL 导出的 CSV 若设了
CHARSET=binary,字段可能含 \x00,必须清洗,否则必炸
用 csv.Read 逐行读比 ReadAll 更省内存,但容易漏掉最后一行
当 CSV 文件末尾没有换行符时,csv.Reader.Read 在读完最后一行后返回 io.EOF,但此时该行数据其实已成功解析到你传入的 []string 中——很多人只检查 err == io.EOF 就跳出循环,结果丢掉最后一行。
- 正确模式是:先
err := r.Read(record),再判断err != nil && err != io.EOF才报错;err == io.EOF且len(record) > 0时,这行有效,要处理 -
ReadAll内部就是这么做的,但它把所有行全 load 到内存,10MB CSV 可能占 30MB+ 内存(Go slice 预分配 + 字符串 header 复制) - 逐行读时,记得复用
record切片:record := make([]string, 0, 16) for { record, err := r.Read(record[:0]) // 复用底层数组 if err != nil { if err == io.EOF { break } log.Fatal(err) } // 处理 record }
修改某列后写回 CSV,字段含逗号或换行符却没加引号
csv.Writer 默认只在字段含逗号、双引号、换行符时自动加双引号,但如果你手动拼接字符串(比如 fmt.Sprintf("%s,%s", a, b))再传给 Write,Writer 不会识别内部结构,直接原样写入,Excel 打开就错行。
立即学习“go语言免费学习笔记(深入)”;
- 永远用
w.Write([]string{a, b, c}),别自己拼 CSV 字符串——Writer 会按 RFC 4180 规则自动转义和包引号 - 字段含双引号时,Writer 自动把它变成两个双引号
"",这是标准行为,别提前 replace 成\"或删掉,否则 Excel 解析失败 - 如果必须手拼(极少见),至少用
strconv.Quote包裹每个字段:quoted := strconv.Quote(field) // 注意:Quote 加的是双引号,且会转义内部双引号和控制符
CSV 看似简单,但 BOM、非法 UTF-8、EOF 边界、引号转义这四点,任意一个没兜住,下游 Excel 或数据库导入就静默失败——它们不报错,只丢数据。










