From b4654a48b0b6e3b43a0f614a371fc34ea0b2404f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Fox?= Date: Thu, 22 Oct 2026 21:03:58 +0200 Subject: [PATCH] Describe this repository --- README.md | 218 +++--------------------------------------------------- 1 file changed, 9 insertions(+), 209 deletions(-) diff --git a/README.md b/README.md index babd5dd..2f798af 100644 --- a/README.md +++ b/README.md @@ -1,213 +1,13 @@ -Go CSV -===== +# Contributions to gocarina/gocsv -The GoCSV package aims to provide easy serialization and deserialization functions to use CSV in Golang +The GoCSV package aims to provide easy CSV serialization and deserialization to the golang programming language -API and techniques inspired from https://godoc.org/gopkg.in/mgo.v2 +This repository holds only my commits to the upstream project, with their original author, date and diff. +Each of my commits is preceded by a snapshot of the upstream files it touched, so every diff shows exactly what I changed. -[![GoDoc](https://godoc.org/github.com/gocarina/gocsv?status.png)](https://godoc.org/github.com/gocarina/gocsv) -[![Build Status](https://travis-ci.org/gocarina/gocsv.svg?branch=master)](https://travis-ci.org/gocarina/gocsv) +## Merged pull requests -Installation -===== - -```go get -u github.com/gocarina/gocsv``` - -Full example -===== - -Consider the following CSV file - -```csv - -client_id,client_name,client_age -1,Jose,42 -2,Daniel,26 -3,Vincent,32 - -``` - -Easy binding in Go! ---- - -```go - -package main - -import ( - "fmt" - "os" - - "github.com/gocarina/gocsv" -) - -type NotUsed struct { - Name string -} - -type Client struct { // Our example struct, you can use "-" to ignore a field - Id string `csv:"client_id"` - Name string `csv:"client_name"` - Age string `csv:"client_age"` - NotUsedString string `csv:"-"` - NotUsedStruct NotUsed `csv:"-"` -} - -func main() { - clientsFile, err := os.OpenFile("clients.csv", os.O_RDWR|os.O_CREATE, os.ModePerm) - if err != nil { - panic(err) - } - defer clientsFile.Close() - - clients := []*Client{} - - if err := gocsv.UnmarshalFile(clientsFile, &clients); err != nil { // Load clients from file - panic(err) - } - for _, client := range clients { - fmt.Println("Hello", client.Name) - } - - if _, err := clientsFile.Seek(0, 0); err != nil { // Go to the start of the file - panic(err) - } - - clients = append(clients, &Client{Id: "12", Name: "John", Age: "21"}) // Add clients - clients = append(clients, &Client{Id: "13", Name: "Fred"}) - clients = append(clients, &Client{Id: "14", Name: "James", Age: "32"}) - clients = append(clients, &Client{Id: "15", Name: "Danny"}) - csvContent, err := gocsv.MarshalString(&clients) // Get all clients as CSV string - //err = gocsv.MarshalFile(&clients, clientsFile) // Use this to save the CSV back to the file - if err != nil { - panic(err) - } - fmt.Println(csvContent) // Display all clients as CSV string - -} - -``` - -Customizable Converters ---- - -```go - -type DateTime struct { - time.Time -} - -// Convert the internal date as CSV string -func (date *DateTime) MarshalCSV() (string, error) { - return date.Time.Format("20060102"), nil -} - -// You could also use the standard Stringer interface -func (date *DateTime) String() (string) { - return date.String() // Redundant, just for example -} - -// Convert the CSV string as internal date -func (date *DateTime) UnmarshalCSV(csv string) (err error) { - date.Time, err = time.Parse("20060102", csv) - return err -} - -type Client struct { // Our example struct with a custom type (DateTime) - Id string `csv:"id"` - Name string `csv:"name"` - Employed DateTime `csv:"employed"` -} - -``` - -Nested structs ---- - -When decoding nested pointer structs, GoCSV allocates the pointers needed to -reach each field. An `omitempty` field still omits an empty leaf pointer value; -it does not prevent allocation of the enclosing structs. - -By default, the fields of nested structs are prefixed with the parent field's -name. For example: - -```go -type Foo struct { - B Bar - X int `csv:"x"` -} - -type Bar struct { - A int `csv:"a"` - B int `csv:"b"` -} -``` - -produces columns `B.a, B.b, x`. - -Use the `csv:"."` tag to inline the nested struct's fields without that prefix; for example: - -```go -type Foo struct { - B Bar `csv:"."` - X int `csv:"x"` -} - -type Bar struct { - A int `csv:"a"` - B int `csv:"b"` -} -``` - -produces columns `a, b, x`. - -Customizable CSV Reader / Writer ---- - -```go - -func main() { - ... - - gocsv.SetCSVReader(func(in io.Reader) gocsv.CSVReader { - r := csv.NewReader(in) - r.Comma = '|' - return r // Allows use pipe as delimiter - }) - - ... - - gocsv.SetCSVReader(func(in io.Reader) gocsv.CSVReader { - r := csv.NewReader(in) - r.LazyQuotes = true - r.Comma = '.' - return r // Allows use dot as delimiter and use quotes in CSV - }) - - ... - - gocsv.SetCSVReader(func(in io.Reader) gocsv.CSVReader { - //return csv.NewReader(in) - return gocsv.LazyCSVReader(in) // Allows use of quotes in CSV - }) - - ... - - gocsv.UnmarshalFile(file, &clients) - - ... - - gocsv.SetCSVWriter(func(out io.Writer) *gocsv.SafeCSVWriter { - writer := csv.NewWriter(out) - writer.Comma = '|' - return gocsv.NewSafeCSVWriter(writer) - }) - - ... - - gocsv.MarshalFile(&clients, file) - - ... -} - -``` +- [Add MarshalBytesWithoutHeaders](https://github.com/gocarina/gocsv/pull/305) (2026-10-12) +- [Fix date layout in README and full example](https://github.com/gocarina/gocsv/pull/304) (2026-10-12) +- [Make SetHeaderNormalizer safe to call while decoding](https://github.com/gocarina/gocsv/pull/303) (2026-10-12) +- [Parse integer fields as base 10 (fixes #182)](https://github.com/gocarina/gocsv/pull/293) (2026-09-05)