commando

package module
v1.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 10, 2022 License: MIT Imports: 11 Imported by: 0

README

Commando, a CSV library for Go

The Commando package aims to provide easy marshalling and unmarshalling of CSV in Go. It’s a fork of gocarina/gocsv, with a simplified API.

Installation

go get -u github.com/evenco/commando

Full example

Consider the following CSV file


client_id,client_name,client_age
1,Jose,42
2,Daniel,26
3,Vincent,32

Easy binding in Go!


package main

import (
	"fmt"
	"os"

	"github.com/evenco/commando"
)

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"`
	NotUsed string `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{}

    // Create an Unmarshaller which deserializes into *Client{}
    unmarshaller, err := commando.NewUnmarshaller(&Client{}, csv.NewReader(clientsFile))
    if err != nil {
        panic(err)
    }

    // Read everything, accumulating in clients
    err = commando.ReadAllCallback(um, func(record interface{}) error {
        clients = append(clients, record.(*Client))
        return nil
    })

	if err != nil {
		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"})

    // Initialize Marshaller for *Client{} structs
    marshaller, err := commando.NewMarshaller(&Client{}, csv.NewWriter(clientsFile))
    if err != nil {
		panic(err)
	}

    for _, client := range clients {
        if err := marshaller.Write(client); err != nil {
            panic(err)
        }
    }
}

Customizable Converters


type DateTime struct {
	time.Time
}

// Convert the internal date as CSV string
func (date *DateTime) MarshalCSV() (string, error) {
	return date.Time.Format("20060201"), 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("20060201", 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"`
}

Documentation

Overview

The Commando package aims to provide easy CSV serialization and deserialization to Go.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoStructTags = errors.New("no csv struct tags found")
)

Functions

func StopOnError

func StopOnError(_ context.Context, err error) error

StopOnError is a helper which stops processing a file on the first encountered error.

Types

type Config

type Config struct {
	// Holder is the type of struct to marshal from/unmarshal info.
	Holder interface{}

	// ErrorHandler is invoked if there's a recoverable error.
	//
	// If the func returns an error, processing stops.  If it returns
	// nil, processing continues.
	//
	// If unset, processing stops on the first error.
	ErrorHandler func(error) error

	// FailIfUnmatchedStructTags indicates whether it is considered an
	// error when there is an unmatched struct tag.
	FailIfUnmatchedStructTags bool

	// FailIfDoubleHeaderNames indicates whether it is considered an
	// error when a header name is repeated in the csv header.
	FailIfDoubleHeaderNames bool

	// ShouldAlignDuplicateHeadersWithStructFieldOrder indicates
	// whether we should align duplicate CSV headers per their
	// alignment in the struct definition.
	ShouldAlignDuplicateHeadersWithStructFieldOrder bool
	// contains filtered or unexported fields
}

func (*Config) NewMarshaller

func (c *Config) NewMarshaller(writer *csv.Writer) (*Marshaller, error)

NewMarshaller creates a marshaller from a csv.Writer. The CSV header will be immediately written to writer.

func (*Config) NewUnmarshaller

func (c *Config) NewUnmarshaller(reader Reader) (*Unmarshaller, error)

NewUnmarshaller creates an unmarshaller from a Reader and a struct.

type Marshaller

type Marshaller struct {
	// contains filtered or unexported fields
}

Marshaller is a CSV to struct marshaller.

func NewMarshaller

func NewMarshaller(holder interface{}, writer *csv.Writer) (*Marshaller, error)

NewMarshaller is a convenience function which allocates and returns a new Marshaller.

func (*Marshaller) Flush

func (m *Marshaller) Flush() error

func (*Marshaller) Write

func (m *Marshaller) Write(record interface{}) error

func (*Marshaller) WriteAll

func (m *Marshaller) WriteAll(values interface{}) error

WriteAll writes every element of values as CSV.

values must be a slice of elements of the configured Holder for this Marshaller.

Flush() must be called when writing is complete.

type NoMarshalFuncError

type NoMarshalFuncError struct {
	// contains filtered or unexported fields
}

NoMarshalFuncError is the custom error type to be raised in case there is no marshal function defined on type

func (NoMarshalFuncError) Error

func (e NoMarshalFuncError) Error() string

type NoUnmarshalFuncError

type NoUnmarshalFuncError struct {
	// contains filtered or unexported fields
}

NoUnmarshalFuncError is the custom error type to be raised in case there is no unmarshal function defined on type

func (NoUnmarshalFuncError) Error

func (e NoUnmarshalFuncError) Error() string

type Reader

type Reader interface {
	Read() ([]string, error)
}

Reader is an interface over csv.Reader, which allows swapping the implementation, if necessary.

type TypeMarshaller

type TypeMarshaller interface {
	MarshalCSV() (string, error)
}

TypeMarshaller is implemented by any value that has a MarshalCSV method This converter is used to convert the value to it string representation

type TypeUnmarshalCSVWithFields

type TypeUnmarshalCSVWithFields interface {
	UnmarshalCSVWithFields(key, value string) error
}

TypeUnmarshalCSVWithFields can be implemented on whole structs to allow for whole structures to customized internal vs one off fields

type TypeUnmarshaller

type TypeUnmarshaller interface {
	UnmarshalCSV(string) error
}

TypeUnmarshaller is implemented by any value that has an UnmarshalCSV method This converter is used to convert a string to your value representation of that string

type Unmarshaller

type Unmarshaller struct {
	// contains filtered or unexported fields
}

Unmarshaller is a CSV to struct unmarshaller.

func NewUnmarshaller

func NewUnmarshaller(holder interface{}, reader Reader) (*Unmarshaller, error)

NewUnmarshaller is a convenience function which allocates and returns a new Unmarshaller.

func NewUnmarshallerWithID added in v1.0.7

func NewUnmarshallerWithID(holder interface{}, reader Reader, idName string) (*Unmarshaller, error)

NewUnmarshallerWithID is a convenience function which allocates and returns a new Unmarshaller with an ID column name specified.

func (*Unmarshaller) Read

func (um *Unmarshaller) Read() (interface{}, error)

Read returns an interface{} whose runtime type is the same as the struct that was used to create the Unmarshaller.

func (*Unmarshaller) ReadAll

func (um *Unmarshaller) ReadAll(ctx context.Context, onError func(ctx context.Context, err error) error) (interface{}, error)

ReadAll returns a slice of structs.

func (*Unmarshaller) ReadAllCallback

func (um *Unmarshaller) ReadAllCallback(ctx context.Context,
	onSuccess func(context.Context, interface{}) error,
	onError func(context.Context, error) error,
) error

ReadAllCallback calls onSuccess for every record Read() from um.

If Read() returns an error, it's passed to onError(), which decides whether to continue processing or stop. If onError() returns nil, processing continues; if it returns an error, processing stops and its error (not the one returned by Read()) is returned.

If onSuccess() returns an error, processing stops and its error is returned.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL