如何在 Golang 中解析带有逗号分隔值 CSV 的字符串

作者:袖梨 2026-06-19
需用 strings.NewReader 将字符串转为 io.Reader 后传入 csv.NewReader;含 BOM 时须手动去除;小数据用 csv.ReadAll,大数据或流式处理用循环 csv.Read;字段含特殊字符需合规引号包裹并设 FieldsPerRecord=-1。

csv.NewReader 解析字符串需包装成 strings.Reader

Go 标准库的 csv.NewReader 只接受 io.Reader,不能直接传字符串。常见错误是试图把 string 直接丢进去,结果编译失败或 panic。

正确做法是用 strings.NewReader 把字符串转成 io.Reader

reader := csv.NewReader(strings.NewReader("a,b,cn1,2,3"))

注意:如果 CSV 内容含 BOM(如 UTF-8-BOM),strings.NewReader 不会自动跳过,可能触发 invalid UTF-8 错误 —— 这时得手动 strip BOM。

csv.Read()csv.ReadAll() 的选择取决于数据规模与内存控制

csv.ReadAll() 会一次性读完所有行并返回 [][]string,适合小数据;csv.Read() 每次只读一行,适合流式处理或大文件(哪怕只是长字符串)。

立即学习“go语言免费学习笔记(深入)”;

  • 若 CSV 行数不确定或可能很大,优先用循环调用 csv.Read()
  • csv.ReadAll() 在遇到空行或格式错误时仍会返回已读部分 + error,不是全有或全无
  • 若首行是 header,可用 reader.Read() 先取 header,再用 reader.Read() 逐行读 data

字段包含逗号、换行或双引号时,必须启用引号解析且确保输入合规

标准 CSV 规范要求:含逗号/换行/双引号的字段要用双引号包裹,内部双引号要写成两个("a""b")。Go 的 csv.Reader 默认支持,但有两个关键点:

  • 必须设置 reader.FieldsPerRecord = -1 允许变长字段(否则遇到不一致列数会报错)
  • 若原始字符串里有未转义的双引号或换行符(比如用户粘贴的脏数据),csv.Read() 会直接返回 error: bare " in non-quoted-field
  • 默认 Comma 是英文逗号,如果实际用分号或制表符,要显式设置 reader.Comma = ';'

解析失败时的常见 error 类型和应对方式

不要只检查 err == nil,不同 error 需区别对待:

  • csv.ParseError:格式错误(如引号不匹配、换行在字段中间),通常应记录原始行并跳过
  • io.EOF:正常结束,尤其在循环读取时要主动判断并 break
  • strconv.Parse* 类 error:发生在你后续把字符串转数字时,和 csv 解析本身无关
  • 空字符串输入会导致 csv.Read() 返回 nil, io.EOF,不是 bug,是设计如此

真正容易被忽略的是:当某行字段数少于 header 时,csv.Reader 不会自动补空字符串,而是原样返回该行切片 —— 你要自己做对齐或校验。

相关文章

精彩推荐