func (e *Encoder) marshal(val reflect.Value, child bool) (cols []string, ok bool) {
	var s string
	switch val.Kind() {
	case reflect.Ptr:
		ok = supportedBaseKind(val)
		if !ok {
			return nil, false
		}
		vv := reflect.Indirect(val)
		switch vv.Kind() {
		case reflect.Invalid:
		default:
			return e.marshal(vv, child)
		}
	case reflect.Struct:
		return e.marshalStruct(val.Interface(), true)
	case reflect.Map:
		s, ok = e.marshalMap(val, child)
		if !ok {
			return nil, false
		}
	case reflect.Array, reflect.Slice:
		s, ok = e.marshalSlice(val, child)
		if !ok {
			return nil, false
		}
	default:
		var ok bool
		s, ok = e.stringify(val, child)
		if !ok {
			return nil, false
		}
	}
	return append(cols, s), true
}
marshal returns the marshaled value. If the received value is not of a
supported Kind, a nil is returned along with false. For supported kinds, a
slice of values is returned along with true.
package struct2csv
import (
	"errors"
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"strings"
)
type StructRequiredError struct {
	kind reflect.Kind
}
func (e StructRequiredError) Error() string {
	return fmt.Sprintf("struct2csv: a value of type struct is required: type was %s", e.kind)
}
type StructSliceError struct {
	kind      reflect.Kind
	sliceKind reflect.Kind
}
func (e StructSliceError) Error() string {
	if e.kind != reflect.Slice {
		return fmt.Sprintf("struct2csv: a type of slice is required: type was %s", e.kind)
	}
	return fmt.Sprintf("struct2csv: a slice of type struct is required: slice type was %s", e.sliceKind)
}
var (
	ErrNilSlice = errors.New("struct2csv: the slice of structs was nil")
	ErrEmptySlice = errors.New("struct2csv: the slice of structs was empty")
)
type stringValues []reflect.Value
func (sv stringValues) Len() int           { return len(sv) }
func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string   { return sv[i].String() }
type Encoder struct {
	useTags  bool
	base     int
	tag      string  
	sepBeg   string
	sepEnd   string
	colNames []string
}
func New() *Encoder {
	return &Encoder{
		useTags: true, base: 10, tag: "csv",
		sepBeg: "(", sepEnd: ")",
	}
}
func (e *Encoder) SetTag(s string) {
	if s == "" {
		return
	}
	e.tag = s
}
func (e *Encoder) SetUseTags(b bool) {
	e.useTags = b
}
func (e *Encoder) SetSeparators(beg, end string) {
	e.sepBeg = beg
	e.sepEnd = end
}
func (e *Encoder) SetBase(i int) {
	if i < 2 {
		i = 2
	}
	e.base = i
}
func (e *Encoder) ColNames() []string {
	ret := make([]string, len(e.colNames))
	_ = copy(ret, e.colNames)
	return ret
}
func (e *Encoder) GetColNames(v interface{}) ([]string, error) {
	if reflect.TypeOf(v).Kind() != reflect.Struct {
		return nil, StructRequiredError{reflect.TypeOf(v).Kind()}
	}
	names := e.getColNames(v)
	e.colNames = make([]string, len(names))
	_ = copy(e.colNames, names)
	return names, nil
}
func (e *Encoder) getColNames(v interface{}) []string {
	typ := reflect.TypeOf(v)
	val := reflect.ValueOf(v)
	var cols []string
	for i := 0; i < typ.NumField(); i++ {
		tF := typ.Field(i)
		if len(tF.PkgPath) > 0 {
			continue
		}
		name := e.getFieldName(tF)
		if name == "" {
			continue
		}
		vF := val.Field(i)
		switch vF.Kind() {
		case reflect.Struct:
			tmp := e.getColNames(vF.Interface())
			cols = append(cols, tmp...)
			continue
		default:
			ok := supportedBaseKind(vF)
			if !ok {
				continue
			}
		}
		cols = append(cols, name)
	}
	return cols
}
func (e *Encoder) GetRow(v interface{}) ([]string, error) {
	if reflect.TypeOf(v).Kind() != reflect.Struct {
		return nil, StructRequiredError{reflect.TypeOf(v).Kind()}
	}
	cols, _ := e.marshalStruct(v, false)
	return cols, nil
}
func (e *Encoder) Marshal(v interface{}) ([][]string, error) {
	if reflect.TypeOf(v).Kind() != reflect.Slice {
		return nil, StructSliceError{kind: reflect.TypeOf(v).Kind()}
	}
	val := reflect.ValueOf(v)
	if val.IsNil() {
		return nil, ErrNilSlice
	}
	if val.Len() == 0 {
		return nil, ErrEmptySlice
	}
	var rows [][]string
	s := val.Index(0)
	switch s.Kind() {
	case reflect.Struct:
		cols := e.getColNames(s.Interface())
		e.colNames = make([]string, len(cols))
		_ = copy(e.colNames, cols)
		rows = append(rows, cols)
	default:
		return nil, StructSliceError{kind: reflect.Slice, sliceKind: s.Kind()}
	}
	for i := 0; i < val.Len(); i++ {
		s := val.Index(i)
		row, ok := e.marshalStruct(s.Interface(), false)
		if !ok {
			continue
		}
		rows = append(rows, row)
	}
	return rows, nil
}