Field names first
Say Where("status", "active"), not "find column 4 and remember the header."
CSV transforms for Go CLIs
simplecsv gives small command-line programs a clear path from raw rows to filtered, reshaped, joined, and summarized output. No database. No query language. Just Go.
$ go run . people.csv
// read once
people, _ := simplecsv.ReadCsvFileE(path)
// field-first transforms
active, _ := people.Where("status", "active")
summary, _ := active.GroupBy(...)
// write a useful result
summary.WriteCsvFileE("report.csv")
ok 3,842 rows -> 17 groups
Why simplecsv
CSV scripts tend to start small. simplecsv keeps them small while taking care of the row-index mistakes and schema surprises that make them brittle.
Say Where("status", "active"), not "find column 4 and remember the header."
Transform methods return independent CSVs. Build a pipeline without hidden changes to earlier values.
Keep storage predictable. Parse numbers only where a filter, sort, or aggregate actually needs them.
Join files, deduplicate rows, reshape columns, group values, and build reports without pulling in a database.
Unique headers and uniform row widths are enforced. Use *E variants when a useful error matters.
Read delimiters and streams, handle BOMs, limit untrusted input, and sanitize spreadsheet-bound output.
A useful first program
Most tools need the same sequence: load, keep the rows that matter, choose the output shape, and write it somewhere useful.
package main
import (
"log"
"strconv"
"github.com/osvik/simplecsv"
)
func main() {
people, err := simplecsv.ReadCsvFileE("people.csv")
if err != nil {
log.Fatal(err)
}
active, ok := people.Where("status", "active")
if !ok {
log.Fatal("status field not found")
}
adults, ok := active.FilterByField("age", func(value string) bool {
age, err := strconv.Atoi(value)
return err == nil && age >= 18
})
if !ok {
log.Fatal("age field not found")
}
result, ok := adults.OnlyThisFields([]string{"id", "name", "age"})
if !ok {
log.Fatal("could not select output fields")
}
if err := result.WriteCsvFileE("active-adults.csv"); err != nil {
log.Fatal(err)
}
}