func (src DataSource) ToCsvFile(name string, columns ...string) error {
	return writeFile(name, func(file io.Writer) error {
		return src.ToCsv(file, columns...)
	})
}
ToCsvFile iterates the data source and writes the selected columns in .csv format to the given file.
The data are written in the "canonical" form with the header on the first line and with all the lines
having the same number of fields, using default settings for the underlying csv.Writer.
package csvplus
import (
	"bytes"
	"encoding/csv"
	"encoding/gob"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"sort"
	"strconv"
	"strings"
	"unsafe"
)
type Row map[string]string
func (row Row) HasColumn(col string) (found bool) {
	_, found = row[col]
	return
}
func (row Row) SafeGetValue(col, subst string) string {
	if value, found := row[col]; found {
		return value
	}
	return subst
}
func (row Row) Header() []string {
	r := make([]string, 0, len(row))
	for col := range row {
		r = append(r, col)
	}
	sort.Strings(r)
	return r
}
func (row Row) String() string {
	if len(row) == 0 {
		return "{}"
	}
	header := row.Header()  
	buff := append(append(append(append([]byte(`{ "`), header[0]...), `" : "`...), row[header[0]]...), '"')
	for _, col := range header[1:] {
		buff = append(append(append(append(append(buff, `, "`...), col...), `" : "`...), row[col]...), '"')
	}
	buff = append(buff, " }"...)
	return *(*string)(unsafe.Pointer(&buff))
}
// SelectExisting takes a list of column names and returns a new Row
// containing only those columns from the list that are present in the current Row.
func (row Row) SelectExisting(cols ...string) Row {
	r := make(map[string]string, len(cols))
	for _, name := range cols {
		if val, found := row[name]; found {
			r[name] = val
		}
	}
	return r
}
// Select takes a list of column names and returns a new Row
// containing only the specified columns, or an error if any column is not present.
func (row Row) Select(cols ...string) (Row, error) {
	r := make(map[string]string, len(cols))
	for _, name := range cols {
		var found bool
		if r[name], found = row[name]; !found {
			return nil, fmt.Errorf(`Missing column %q`, name)
		}
	}
	return r, nil
}
// SelectValues takes a list of column names and returns a slice of their
// corresponding values, or an error if any column is not present.
func (row Row) SelectValues(cols ...string) ([]string, error) {
	r := make([]string, len(cols))
	for i, name := range cols {
		var found bool
		if r[i], found = row[name]; !found {
			return nil, fmt.Errorf(`Missing column %q`, name)
		}
	}
	return r, nil
}
// Clone returns a copy of the current Row.
func (row Row) Clone() Row {
	r := make(map[string]string, len(row))
	for k, v := range row {
		r[k] = v
	}
	return r
}
// ValueAsInt returns the value of the given column converted to integer type, or an error.
// The column must be present on the row.
func (row Row) ValueAsInt(column string) (res int, err error) {
	var val string
	var found bool
	if val, found = row[column]; !found {
		err = fmt.Errorf(`Missing column %q`, column)
		return
	}
	if res, err = strconv.Atoi(val); err != nil {
		if e, ok := err.(*strconv.NumError); ok {
			err = fmt.Errorf(`Column %q: Cannot convert %q to integer: %s`, column, val, e.Err)
		} else {
			err = fmt.Errorf(`Column %q: %s`, column, err)
		}
	}
	return
}
// ValueAsFloat64 returns the value of the given column converted to floating point type, or an error.
// The column must be present on the row.
func (row Row) ValueAsFloat64(column string) (res float64, err error) {
	var val string
	var found bool
	if val, found = row[column]; !found {
		err = fmt.Errorf(`Missing column %q`, column)
		return
	}
	if res, err = strconv.ParseFloat(val, 64); err != nil {
		if e, ok := err.(*strconv.NumError); ok {
			err = fmt.Errorf(`Column %q: Cannot convert %q to float: %s`, column, val, e.Err)
		} else {
			err = fmt.Errorf(`Column %q: %s`, column, err.Error())
		}
	}
	return
}
// RowFunc is the function type used when iterating Rows.
type RowFunc func(Row) error
// DataSource is the iterator type used throughout this library. The iterator
// calls the given RowFunc once per each row. The iteration continues until
// either the data source is exhausted or the supplied RowFunc returns a non-nil error, in
// which case the error is returned back to the caller of the iterator. A special case of io.EOF simply
// stops the iteration and the iterator function returns nil error.
type DataSource func(RowFunc) error
// TakeRows converts a slice of Rows to a DataSource.
func TakeRows(rows []Row) DataSource {
	return func(fn RowFunc) error {
		return iterate(rows, fn)
	}
}
// the core iteration
func iterate(rows []Row, fn RowFunc) (err error) {
	var row Row
	var i int
	for i, row = range rows {
		if err = fn(row.Clone()); err != nil {
			break
		}
	}
	switch err {
	case nil:
		// nothing to do
	case io.EOF:
		err = nil // end of iteration
	default:
		// wrap error
		err = &DataSourceError{
			Line: uint64(i),
			Err:  err,
		}
	}
	return
}
// Take converts anything with Iterate() method to a DataSource.
func Take(src interface {
	Iterate(fn RowFunc) error
}) DataSource {
	return src.Iterate
}
// Transform is the most generic operation on a Row. It takes a function that
// maps a Row to another Row and an error. Any error returned from that function
// stops the iteration, otherwise the returned Row, if not empty, gets passed
// down to the next stage of the processing pipeline.
func (src DataSource) Transform(trans func(Row) (Row, error)) DataSource {
	return func(fn RowFunc) error {
		return src(func(row Row) (err error) {
			if row, err = trans(row); err == nil && len(row) > 0 {
				err = fn(row)
			}
			return
		})
	}
}
// Filter takes a predicate which, when applied to a Row, decides if that Row
// should be passed down for further processing. The predicate should return 'true' to pass the Row.
func (src DataSource) Filter(pred func(Row) bool) DataSource {
	return func(fn RowFunc) error {
		return src(func(row Row) (err error) {
			if pred(row) {
				err = fn(row)
			}
			return
		})
	}
}
// Map takes a function which gets applied to each Row when the source is iterated over. The function
// may return a modified input Row, or an entirely new Row.
func (src DataSource) Map(mf func(Row) Row) DataSource {
	return func(fn RowFunc) error {
		return src(func(row Row) error {
			return fn(mf(row))
		})
	}
}
// Validate takes a function which checks every Row upon iteration and returns an error
// if the validation fails. The iteration stops at the first error encountered.
func (src DataSource) Validate(vf func(Row) error) DataSource {
	return func(fn RowFunc) error {
		return src(func(row Row) (err error) {
			if err = vf(row); err == nil {
				err = fn(row)
			}
			return
		})
	}
}
// Top specifies the number of Rows to pass down the pipeline before stopping the iteration.
func (src DataSource) Top(n uint64) DataSource {
	return func(fn RowFunc) error {
		counter := n
		return src(func(row Row) error {
			if counter == 0 {
				return io.EOF
			}
			counter--
			return fn(row)
		})
	}
}
// Drop specifies the number of Rows to ignore before passing the remaining rows down the pipeline.
func (src DataSource) Drop(n uint64) DataSource {
	return func(fn RowFunc) error {
		counter := n
		return src(func(row Row) error {
			if counter == 0 {
				return fn(row)
			}
			counter--
			return nil
		})
	}
}
// TakeWhile takes a predicate which gets applied to each Row upon iteration.
// The iteration stops when the predicate returns 'false'.
func (src DataSource) TakeWhile(pred func(Row) bool) DataSource {
	return func(fn RowFunc) error {
		var done bool
		return src(func(row Row) error {
			if done = (done || !pred(row)); done {
				return io.EOF
			}
			return fn(row)
		})
	}
}
// DropWhile ignores all the Rows for as long as the specified predicate is true;
// afterwards all the remaining Rows are passed down the pipeline.
func (src DataSource) DropWhile(pred func(Row) bool) DataSource {
	return func(fn RowFunc) error {
		var yield bool
		return src(func(row Row) (err error) {
			if yield = (yield || !pred(row)); yield {
				err = fn(row)
			}
			return
		})
	}
}
// ToCsv iterates the data source and writes the selected columns in .csv format to the given io.Writer.
// The data are written in the "canonical" form with the header on the first line and with all the lines
// having the same number of fields, using default settings for the underlying csv.Writer.
func (src DataSource) ToCsv(out io.Writer, columns ...string) (err error) {
	if len(columns) == 0 {
		panic("Empty column list in ToCsv() function")
	}
	w := csv.NewWriter(out)
	// header
	if err = w.Write(columns); err == nil {
		// rows
		err = src(func(row Row) (e error) {
			var values []string
			if values, e = row.SelectValues(columns...); e == nil {
				e = w.Write(values)
			}
			return
		})
	}
	if err == nil {
		w.Flush()
		err = w.Error()
	}
	return
}
// ToCsvFile iterates the data source and writes the selected columns in .csv format to the given file.
// The data are written in the "canonical" form with the header on the first line and with all the lines