tocsv

package module
v0.0.0-...-b014e4e Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2025 License: MIT Imports: 11 Imported by: 0

README

tocsv - Universal CSV Export Library for Go

A library for exporting any data to CSV with full customization options

Quick Start

Installation
go get github.com/go-data-exporter/tocsv
Basic Usage
From SQL Results
package main

import (
	"database/sql"
	"log"
	"os"

	"github.com/go-data-exporter/tocsv"
)

func main() {
	var (
		driver = "pgx"
		dsn    = "postgres://"
	)
	db, err := sql.Open(driver, dsn)
	if err != nil {
		log.Fatalln(err)
	}
	defer db.Close()
	rows, err := db.Query("SELECT id, name, email FROM users")
	if err != nil {
		log.Fatalln(err)
	}
	defer rows.Close()

	writer := tocsv.New(tocsv.NewSQLRowsScanner(rows, driver))
	writer.Write(os.Stdout)
}
From Slice Data
package main

import (
	"os"

	"github.com/go-data-exporter/tocsv"
)

func main() {
	data := [][]any{
		{1, "John Doe", "john@example.com"},
		{2, "Jane Smith", "jane@example.com"},
	}
	rows := tocsv.NewSliceRowsScanner(data)
	writer := tocsv.New(rows)
	writer.Write(os.Stdout)
}
From any other data source

You could create your own implementation of tocsv.RowsScanner interface.

type RowsScanner interface {
	// Next prepares the next result row for reading.
	// Returns true on success, false if no more rows are available.
	Next() bool

	// Scan copies the current row's values into the provided destinations.
	// Each destination must be a pointer to an any value (*any).
	Scan(dest ...any) error

	// Columns returns the column metadata for the current result set.
	Columns() ([]Column, error)

	// Driver returns an identifier for the data source driver.
	Driver() string

	// Err returns any error that occurred during iteration.
	Err() error
}
Advanced Customization
Custom Type Handling
package main

import (
	"os"

	"github.com/go-data-exporter/tocsv"
)

type User struct {
	Firstname string
	Lastname  string
}

func main() {
	data := [][]any{
		{1, User{"User", "1"}},
		{2, User{"User", "2"}},
		{3, User{"User", "3"}},
	}
	writer := tocsv.New(tocsv.NewSliceRowsScanner(data),
		tocsv.WithCustomType(func(u User, _ string, _ tocsv.Column) string {
			return u.Firstname + " " + u.Lastname
		}),
	)
	writer.Write(os.Stdout)
}
Row Processing Callback
package main

import (
	"os"
	"strings"

	"github.com/go-data-exporter/tocsv"
)

type User struct {
	Firstname string
	Lastname  string
}

func main() {
	data := [][]any{
		{1, User{"user", "1"}},
		{2, User{"user", "2"}},
		{3, User{"user", "3"}},
	}
	writer := tocsv.New(tocsv.NewSliceRowsScanner(data),
		tocsv.WithCustomType(func(u User, _ string, _ tocsv.Column) string {
			return u.Firstname + " " + u.Lastname
		}),
		tocsv.WithCallback(func(row []string) ([]string, bool) {
			// Skip "user 2"
			if row[1] == "user 2" {
				return nil, false
			}
			// Uppercase names
			row[1] = strings.ToUpper(row[1])
			return row, true
		}),
	)
	writer.Write(os.Stdout)
}
Custom Headers
writer := tocsv.New(rows,
    tocsv.WithCustomHeader([]string{"User ID", "Full Name", "Email Address"}),
    tocsv.WithHeader(true),
)
Configuration Options
Option Description Example
WithCustomDelimiter Set field delimiter WithCustomDelimiter(';')
WithCRLF Use Windows line endings WithCRLF(true)
WithHeader Toggle header row WithHeader(false)
WithCustomHeader Custom column names WithCustomHeader([]string{"ID", "Name"})
WithCustomNULL NULL value representation WithCustomNULL("NULL")
WithCustomType Type conversion handler See example above
WithCallback Row processing callback WithCallback(filterRows)
Performance
  • The library is optimized for efficient memory usage:
  • Processes data in streaming fashion
  • Minimal allocations during conversion
  • Batched CSV writing
License

MIT - See LICENSE for details.

Documentation

Overview

Package tocsv provides tools for converting various data sources to CSV format. It supports SQL database results, slices, and custom data sources through a unified RowsScanner interface with extensive customization options.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(rs RowsScanner, opts ...Option) *csvWriter

New creates a new csvWriter instance with the given RowsScanner and options.

Example:

writer := tocsv.New(rows,
    tocsv.WithCustomDelimiter(';'),
    tocsv.WithHeader(false),
)

Types

type Column

type Column struct {
	Name string // The name of the column
	Type string // The type of the column (database type name or Go type)
}

Column represents metadata about a single column in the data source. It contains the column name and its type information.

type Option

type Option func(*csvWriter)

Option represents a functional option for configuring csvWriter behavior.

func WithCRLF

func WithCRLF(useCRLF bool) Option

WithCRLF configures whether to use CRLF line endings (default is false).

func WithCallback

func WithCallback(fn func(row []string) ([]string, bool)) Option

WithCallback sets a row processing callback function. The callback can modify or filter rows before writing. Return modified row and true to write, or false to skip.

func WithCustomDelimiter

func WithCustomDelimiter(delimiter rune) Option

WithCustomDelimiter sets a custom field delimiter (default is comma).

func WithCustomHeader

func WithCustomHeader(customHeader []string) Option

WithCustomHeader sets custom column headers (must match column count).

func WithCustomNULL

func WithCustomNULL(nullValue string) Option

WithCustomNULL sets the string representation for NULL values (default is empty).

func WithCustomType

func WithCustomType[T any](fn func(v T, driver string, column Column) string) Option

WithCustomType registers a custom conversion function for type T. The provided function will be called to convert values of type T to strings.

func WithHeader

func WithHeader(writeHeader bool) Option

WithHeader configures whether to write column headers (default is true).

type RowsScanner

type RowsScanner interface {
	// Next prepares the next result row for reading.
	// Returns true on success, false if no more rows are available.
	Next() bool

	// Scan copies the current row's values into the provided destinations.
	// Each destination must be a pointer to an any value (*any).
	Scan(dest ...any) error

	// Columns returns the column metadata for the current result set.
	Columns() ([]Column, error)

	// Driver returns an identifier for the data source driver.
	Driver() string

	// Err returns any error that occurred during iteration.
	Err() error
}

RowsScanner is an interface that abstracts data source scanning for CSV conversion. It mimics sql.Rows behavior but works with any tabular data source.

func NewSQLRowsScanner

func NewSQLRowsScanner(rows *sql.Rows, driver string) RowsScanner

NewSQLRowsScanner creates a RowsScanner from sql.Rows. driver specifies the database driver name (e.g., "mysql", "postgres").

func NewSliceRowsScanner

func NewSliceRowsScanner(rows [][]any) RowsScanner

NewSliceRowsScanner creates a RowsScanner from a 2D slice. Each inner slice represents a row of values.

Jump to

Keyboard shortcuts

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