Start here

From CSV file to useful command.

Install one package, read a file, compose a few field-first operations, and write a result. The library stays out of your CLI framework and lets your program own the interface.

Install

Use the module directly in a Go project:

go get github.com/osvik/simplecsv

Then import it where your command reads or transforms CSV data:

import "github.com/osvik/simplecsv"

Your first transform

This complete program keeps active adults, selects the columns that belong in the export, and writes a new file.

package main

import (
    "log"
    "strconv"

    "github.com/osvik/simplecsv"
)

func main() {
    input, err := simplecsv.ReadCsvFileE("people.csv")
    if err != nil {
        log.Fatal(err)
    }

    active, ok := input.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")
    }

    output, ok := adults.OnlyThisFields([]string{"id", "name", "age"})
    if !ok {
        log.Fatal("could not select fields")
    }

    if err := output.WriteCsvFileE("active-adults.csv"); err != nil {
        log.Fatal(err)
    }
}

Use streams for Unix-style tools

File helpers are convenient, but simplecsv also reads from any io.Reader and writes to any io.Writer. That makes stdin and stdout natural command-line interfaces.

package main

import (
    "log"
    "os"

    "github.com/osvik/simplecsv"
)

func main() {
    input, err := simplecsv.ReadCsv(os.Stdin, ',')
    if err != nil {
        log.Fatal(err)
    }

    output, ok := input.WhereFold("status", "active")
    if !ok {
        log.Fatal("status field not found")
    }

    if err := output.WriteTo(os.Stdout, ','); err != nil {
        log.Fatal(err)
    }
}

Three rules worth remembering

  1. Row zero is the header.Data rows start at index 1. Prefer *ByField, Where, and FilterByField so header arithmetic stays out of your program.
  2. Cells are strings.Convert at the edge of the operation with strconv. Storage remains a predictable string model.
  3. Transformations return copies.Methods such as Where, SortByField, and GroupBy do not mutate their receiver or share row slices.
Need reasons instead of booleans?

Use error-returning variants such as JoinE, GroupByE, ConcatE, and ConcatByNameE. The original boolean APIs remain available for short scripts.

Next steps

Pick a workflow and copy the smallest recipe that matches it:

Browse recipes ->