gocsv

Struct-tag-based CSV marshaling and unmarshaling for Go, modeled after encoding/json.

Library
Go
vv0.0.0-20260905190356-869064524258
2,190stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
66/100Good
Development Activity72
Maintenance24
Community68
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
64/100Good
Architecture72
Code Quality74
Innovation55
Learning Curve55

GoCSV brings the ergonomics of Go’s encoding/json package to CSV files: annotate struct fields with csv:"..." tags and the library handles reading rows into structs and writing structs back out as CSV, including nested/embedded structs, custom type converters, and header normalization. It wraps the standard library’s encoding/csv reader and writer rather than replacing them, so callers can plug in a custom delimiter, quoting behavior, or error-handling strategy while still getting reflection-driven struct binding on top.

Beyond simple file-to-struct binding, gocsv exposes streaming entry points (UnmarshalToChan, UnmarshalToCallback) for processing large CSV files row-by-row without loading the whole file into memory, plus a two-column CSVToMap helper for the common case of turning a CSV into a Go map. It’s a dependency-free, single-purpose library aimed at Go services and CLIs that need to import or export tabular data without hand-writing per-field encoding/csv boilerplate.

What You Get

  • Struct-tag-driven Marshal/Unmarshal functions for files, strings, byte slices, and io.Reader/io.Writer
  • Nested and embedded struct support, with dotted csv:"." tags to inline fields without column-name prefixing
  • Pluggable CSV reader/writer via SetCSVReader/SetCSVWriter for custom delimiters, quoting, and lazy-quote parsing
  • Streaming decode helpers (UnmarshalToChan, UnmarshalToCallback, UnmarshalToCallbackWithError) for large files
  • Custom per-type converters via the TypeMarshaller/TypeUnmarshaller interfaces and encoding.TextMarshaler support
  • Header normalization hooks (SetHeaderNormalizer) for case-insensitive or fuzzy struct/CSV header matching

Common Use Cases

  • Importing CSV exports (billing data, user lists, inventory feeds) directly into typed Go structs
  • Exporting query results or report data from a Go service as downloadable CSV files
  • Streaming very large CSV files into a channel or callback to avoid loading them fully into memory
  • Building CLI tools that read/write CSV as a data interchange format between systems
  • Converting simple two-column CSV files into Go maps for lookup tables or config data

Under The Hood

Architecture The package is organized as a single flat gocsv package split by concern: csv.go exposes the public Marshal*/Unmarshal* API surface as thin wrappers, decode.go defines the Decoder/SimpleDecoder/CSVReader interfaces plus header-mismatch validation (mismatchStructFields, mismatchHeaderFields), reflect.go builds and caches per-type fieldInfo/structInfo via reflection in a sync.Map so struct introspection happens once per type, types.go defines the TypeMarshaller/TypeUnmarshaller conversion interfaces bridging Go values and CSV strings, and safe_csv.go wraps encoding/csv.Writer to surface write errors safely. Every marshal/unmarshal call path funnels through the shared structInfoCache, so callers that change the header normalizer (SetHeaderNormalizer) trigger an explicit cache reset — a central point that all encode/decode operations depend on.

Tech Stack gocsv has zero third-party dependencies — go.mod declares only the module path and a Go 1.13 minimum, with everything built on encoding/csv (wrapped as CSVReader/SafeCSVWriter), reflect for struct introspection, encoding.TextMarshaler for interop with the standard marshaling interfaces, and sync/sync.Map for concurrent-safe caching. It’s a self-contained importable package with no runtime, database, or network dependencies, installed via go get.

Code Quality Seven dedicated test files (csv_test.go, decode_test.go, encode_test.go, reflect_test.go, types_test.go, unmarshaller_test.go, custom_unmarshaller_test.go) give extensive coverage of the public API and internal helpers using Go’s standard testing package. Errors are explicit and typed rather than swallowed — sentinel errors (ErrUnmatchedStructTags, ErrDoubleHeaderNames, ErrEmptyCSVFile, ErrNoStructTags) are wrapped with %w, and dedicated NoMarshalFuncError/NoUnmarshalFuncError types carry descriptive messages. Naming follows idiomatic Go conventions, and both a legacy Travis config and a modern GitHub Actions workflow run CI, though no linter configuration is present in the repo.

What Makes It Unique gocsv doesn’t introduce a new parsing model — it applies the well-established encoding/json struct-tag pattern (explicitly credited to gopkg.in/mgo.v2’s techniques) to CSV. Its practical differentiators are a pluggable reader/writer for custom delimiters and lazy quoting, a header normalizer hook for fuzzy/case-insensitive column matching, zero-width-character stripping for real-world messy CSV headers, dotted-tag struct inlining, and a comprehensive set of channel- and callback-based streaming unmarshal variants for processing large files without loading them fully into memory.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search