func Take(src interface {
	Iterate(fn RowFunc) error
}) DataSource {
	return src.Iterate
}
Take converts anything with Iterate() method to a DataSource.
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))
}
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
}
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
}
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
}
func (row Row) Clone() Row {
	r := make(map[string]string, len(row))
	for k, v := range row {
		r[k] = v
	}
	return r
}
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
}
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
}
type RowFunc func(Row) error
type DataSource func(RowFunc) error
func TakeRows(rows []Row) DataSource {
	return func(fn RowFunc) error {
		return iterate(rows, fn)
	}
}
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:
	case io.EOF:
		err = nil  
	default:
		err = &DataSourceError{
			Line: uint64(i),
			Err:  err,
		}
	}
	return
}