

新闻资讯
行业动态用 encoding/csv 读取标准 CSV 文件最稳妥,但需确保 UTF-8 无 BOM;GBK 等编码须先转码;大文件应流式 Read 避免 OOM;写入时需防 Excel 公式注入。
encoding/csv 读取标准 CSV 文件最稳妥Go 标准库的 encoding/csv 包是处理合规 CSV 的首选,它能正确解析带引号、换行、逗号转义的字段,不用自己写状态机。但前提是文件编码为 UTF-8,且无 BOM;遇到 GBK 或含 BOM 的文件会直接报错 invalid UTF-8。
常见错误现象:record on line X: wrong number of fields —— 多半是某行字段被双引号包裹后内部含换行符,而你用了 Read() 而非 ReadAll(),导致按行切割失败。
csv.NewReader(file) 包裹 *os.File 或 io.Reader,别直接读字节流r.Read() 获取 header,再用 r.ReadAll() 读余下数据(ReadAll 内部已处理跨行字段)"abc""def" 表示 abc"def;不支持单引号或反斜杠转义file, _ := os.Open("data.csv")
r := csv.NewReader(file)
records, err := r
.ReadAll()
if err != nil {
log.Fatal(err)
}
for i, record := range records {
fmt.Printf("row %d: %v\n", i, record)
}
Windows 记事本保存的 CSV 常带 UTF-8 BOM(\xEF\xBB\xBF),csv.NewReader 会把它当非法字符报错。GBK/GB2312 文件更常见于老系统导出数据,标准包完全不识别。
\xEF\xBB\xBF,则用 io.MultiReader(bytes.NewReader([]byte{}), file) 跳过golang.org/x/text/encoding/charmap 中的 GB18030(兼容 GBK)解码,再传给 csv.NewReader
strings.ReplaceAll 或正则“删 BOM”——BOM 可能出现在任意位置,且 UTF-8 多字节序列不能简单字节替换file, _ := os.Open("gbk.csv")
defer file.Close()
decoder := charmap.GB18030.NewDecoder()
reader := transform.NewReader(file, decoder)
r := csv.NewReader(reader)
records, _ := r.ReadAll()
ReadAll 导致 OOMReadAll 会把整个文件加载进内存,100MB CSV 可能吃掉 500MB+ 内存(字符串重复分配、slice 扩容)。真实业务中应流式处理,尤其做 ETL 或导入数据库时。
for record, err := r.Read(); err == nil; record, err = r.Read() 循环逐行读,每行处理完立即释放引用record 是切片,底层共用同一块缓冲区,若需长期保存某行,必须 append([]string{}, record...) 拷贝r.Comma = '\t' 可读 TSV;r.TrimLeadingSpace = true 自动去字段前导空格(但不去引号内空格)CSV 本身不是执行环境,但若导出数据被 Excel 打开,字段以 =、+、-、@ 开头,Excel 会误判为公式执行——这属于客户端风险,但服务端可主动规避。
=、+、-、@ 开头,统一在前面加单引号 '(Excel 会显示该引号,但不执行)csv.Write 自动加引号:它只在含逗号、换行或引号时才包裹,对公式前缀无效真正难处理的是嵌套结构(如 JSON 字段)、超长字段截断、以及缺失值统一标记(NULL 还是空字符串)。这些得结合业务定规则,标准库只管语法,不管语义。