Skip to content
Go Basics: Parse CSV Records Without Splitting on Commas

Go Basics: Parse CSV Records Without Splitting on Commas

October 31, 2026

A comma inside a quoted product name is data, not a separator. Use encoding/csv to read complete records and keep field-count validation separate from numeric validation.

Prepare a scratch directory

Tested on Linux amd64 with Go 1.26.10. Install Go and make go available on PATH. You also need Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The example uses only the standard library and needs no module or external dependency.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as csv-records-demo.go:

package main

import (
	"encoding/csv"
	"errors"
	"fmt"
	"io"
	"strings"
)

func main() {
	reader := csv.NewReader(strings.NewReader("name,quantity\n\"tea, green\",2\ncoffee,3\n"))
	reader.FieldsPerRecord = 2
	for {
		record, err := reader.Read()
		if errors.Is(err, io.EOF) {
			break
		}
		if err != nil {
			panic(err)
		}
		fmt.Printf("Fields: %q\n", record)
	}
	bad := csv.NewReader(strings.NewReader("tea,2,extra\n"))
	bad.FieldsPerRecord = 2
	_, err := bad.Read()
	fmt.Println("Wrong field count:", errors.Is(err, csv.ErrFieldCount))
}

Run it:

go run csv-records-demo.go

Observed output:

Fields: ["name" "quantity"]
Fields: ["tea, green" "2"]
Fields: ["coffee" "3"]
Wrong field count: true

Read the result

The quoted product name remains a single field. FieldsPerRecord = 2 makes the schema explicit instead of deriving it from the first record. The deliberate malformed record returns an error that wraps csv.ErrFieldCount, which errors.Is can recognize.

Apply it carefully

CSV parsing returns strings. Validate quantities and required headers separately before using the records. Quoted records may span multiple physical lines, so do not split input into lines before handing it to this parser. This example stops on unexpected errors instead of using partial records.

The official Go reference documents the behavior used here.

Clean up

Remove the saved source, return to the starting directory, and remove the empty practice directory. go run does not leave an executable here; Go manages its build cache separately.

rm -- csv-records-demo.go
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on