func MakeAllNodes(o Options, vs ...interface{}) []*Nodes {
	allNodes := make([]*Nodes, 0)
	for _, v := range vs {
		nodes := MakeNodes(o, v)
		allNodes = append(allNodes, nodes)
	}
	return allNodes
}
MakeAllNodes returns a slice of *Nodes from the provided options and
interfaces.
package node
import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
	"github.com/pcelvng/go-config/util"
)
type Nodes struct {
	nodesMap   map[string]*Node  
	nodesSlice []*Node           
	v          interface{}       
}
func (ns *Nodes) Map() map[string]*Node {
	return ns.nodesMap
}
func (ns *Nodes) List() []*Node {
	return ns.nodesSlice
}
func (ns *Nodes) StructPtr() interface{} {
	return ns.v
}
func (ns *Nodes) SetTag(fieldName, key, value string) error {
	n, ok := ns.nodesMap[fieldName]
	if !ok {
		return errors.New("unable to set field tag: no field found by name '" + fieldName + "'")
	}
	n.SetTag(key, value)
	return nil
}
type Node struct {
	Prefix string  
	FieldValue reflect.Value
	Field      reflect.StructField
	Index int
	tag map[string]string
	meta map[string]string
}
func (n *Node) FieldName() string {
	return n.Field.Name
}
func (n *Node) FullName() string {
	if n.Prefix == "" {
		return n.FieldName()
	}
	return n.Prefix + "." + n.FieldName()
}
func (n *Node) ParentName() string {
	return n.Prefix
}
func (n *Node) ParentsNames() []string {
	names := make([]string, 0)
	if n.ParentName() == "" {
		return names
	}
	lineage := strings.Split(n.ParentName(), ".")
	for i := 0; i < len(lineage); i++ {
		names = append(names, strings.Join(lineage[:i+1], "."))
	}
	return names
}
func (n *Node) ValueType() string {
	return n.FieldValue.Type().String()
}
func (n *Node) Kind() reflect.Kind {
	return n.FieldValue.Kind()
}
func (n *Node) SetTag(key, value string) {
	if value == "" || key == "" {
		return
	}
	n.tag[key] = value
}
func (n *Node) GetTag(key string) string {
	if v, ok := n.tag[key]; ok {
		return v
	}
	return n.Field.Tag.Get(key)
}
func (n *Node) SetMeta(key, value string) {
	if value == "" || key == "" {
		return
	}
	n.meta[key] = value
}
func (n *Node) GetMeta(key string) string {
	return n.meta[key]
}
func (n *Node) GetBoolTag(key string) bool {
	bv, _ := strconv.ParseBool(n.GetTag(key))
	return bv
}
func (n *Node) SetBoolTag(key string, value bool) {
	n.SetTag(key, strconv.FormatBool(value))
}
func (n *Node) IsStruct() bool {
	return n.Kind() == reflect.Struct
}
func (n *Node) IsString() bool {
	return n.Kind() == reflect.String
}
func (n *Node) IsDuration() bool {
	return n.ValueType() == "time.Duration"
}
func (n *Node) IsTime() bool {
	if n == nil {
		return false
	}
	return n.ValueType() == "time.Time"
}
func (n *Node) IsSlice() bool {
	return n.Kind() == reflect.Slice
}
func (n *Node) IsStringSlice() bool {
	if n.Kind() == reflect.Slice {
		baseType := reflect.TypeOf(n.FieldValue.Interface()).Elem()
		return baseType.Kind() == reflect.String
	}
	return false
}
func (n *Node) IsBool() bool {
	return n.Kind() == reflect.Bool
}
func fieldString(value reflect.Value) string {
	switch value.Kind() {
	case reflect.String:
		return value.String()
	case reflect.Bool:
		return strconv.FormatBool(value.Bool())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if value.Type().String() == "time.Duration" {
			return value.Interface().(time.Duration).String()
		}
		return strconv.FormatInt(value.Int(), 10)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.FormatUint(value.Uint(), 10)
	case reflect.Float32, reflect.Float64:
		f := fmt.Sprintf("%f", value.Float())  
		f = strings.TrimRight(f, "0")
		return strings.TrimRight(f, ".")  
	default:
		panic(fmt.Sprintf("unexpected king to convert to string '%v'", value.Kind().String()))
	}
}
func (n *Node) String() string {
	return fieldString(n.FieldValue)
}
func (n *Node) SliceString() []string {
	if !n.IsSlice() {
		panic(fmt.Sprintf("field value '%v' must be a slice and instead was '%v'",
			n.FullName(),
			n.FieldValue.Kind().String()),
		)
	}
	items := make([]string, 0)
	for i := 0; i < n.FieldValue.Len(); i++ {
		itemValue := n.FieldValue.Index(i)
		if itemValue.Kind() == reflect.Ptr {
			itemValue = itemValue.Elem()
		}
		items = append(items, fieldString(itemValue))
	}
	return items
}
func (n *Node) TimeString(timeFmt string) string {
	if !n.IsTime() {
		panic(fmt.Sprintf("field '%v' must be a 'time.Time' value type but is '%v' instead",
			n.FullName(),
			n.ValueType(),
		))
	}
	timeFmt = NormTimeFormat(timeFmt)
	tv := n.FieldValue.Interface().(time.Time)
	if tv.IsZero() {
		return ""
	}
	return tv.Format(timeFmt)
}
func (n *Node) SetFieldValue(s string) error {
	switch n.Kind() {
	case reflect.Ptr:
		panic(fmt.Sprintf("node '%s' type is a pointer", n.FullName()))
	case reflect.Slice:
		panic(fmt.Sprintf("node '%s' type is a slice - call SetSlice method instead", n.FullName()))
	case reflect.Struct:
		panic(fmt.Sprintf("node '%s' type is a struct - call SetStruct method instead", n.FullName()))
	}
	return setField(n.FieldValue, s)
}
func (n *Node) SetSlice(vals []string) error {
	if !n.IsSlice() {
		panic(fmt.Sprintf("field value '%v' must be a slice and instead was '%v'",
			n.FullName(),
			n.FieldValue.Kind().String()),
		)
	}
	fValue := n.FieldValue
	baseType := reflect.TypeOf(fValue.Interface()).Elem()
	slice := reflect.MakeSlice(fValue.Type(), 0, len(vals))
	for _, v := range vals {
		baseValue := reflect.New(baseType).Elem()
		err := setField(baseValue, v)
		if err != nil {
			return err
		}
		slice = reflect.Append(slice, baseValue)
	}
	fValue.Set(slice)
	return nil
}
func setField(value reflect.Value, s string) error {
	switch value.Kind() {
	case reflect.String:
		value.SetString(s)
	case reflect.Bool:
		switch strings.ToLower(s) {
		case "true":
			value.SetBool(true)
		case "false", "":
			value.SetBool(false)
		default:
			return fmt.Errorf("cannot assign '%v' to bool type", s)
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if value.Type().String() == "time.Duration" {
			d, err := time.ParseDuration(s)
			if err != nil {
				return err
			}
			value.SetInt(int64(d))
			return nil
		}
		i, err := strconv.ParseInt(s, 10, 0)
		if err != nil {
			return err
		}
		value.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		i, err := strconv.ParseUint(s, 10, 0)
		if err != nil {
			return err
		}
		value.SetUint(i)
	case reflect.Float32, reflect.Float64:
		f, err := strconv.ParseFloat(s, 0)
		if err != nil {
			return err
		}
		value.SetFloat(f)
	case reflect.Ptr:
		z := reflect.New(value.Type().Elem())
		err := setField(z.Elem(), s)
		if err != nil {
			return err
		}
		value.Set(z)
	default:
		return fmt.Errorf("unsupported type '%v'", value.Kind())
	}
	return nil
}
func (n *Node) SetStruct(v interface{}) {
	if n.FieldValue.Kind() != reflect.Struct {
		panic(
			fmt.Sprintf("attempting to assign struct to '%s' on non-struct type '%s'",
				n.FullName(), n.ValueType()),
		)
	}
	n.FieldValue.Set(reflect.ValueOf(v))
}
var timeFormats = map[string]string{
	"ANSIC":       time.ANSIC,
	"UnixDate":    time.UnixDate,
	"RubyDate":    time.RubyDate,
	"RFC822":      time.RFC822,
	"RFC822Z":     time.RFC822Z,
	"RFC850":      time.RFC850,
	"RFC1123":     time.RFC1123,
	"RFC1123Z":    time.RFC1123Z,
	"RFC3339":     time.RFC3339,
	"RFC3339Nano": time.RFC3339Nano,
	"Kitchen":     time.Kitchen,
	"Stamp":       time.Stamp,
	"StampMilli":  time.StampMilli,
	"StampMicro":  time.StampMicro,
	"StampNano":   time.StampNano,
}
func NormTimeFormat(timeFmt string) string {
	if timeFmt == "" {
		return time.RFC3339
	}
	mappedFmt, ok := timeFormats[timeFmt]
	if ok {
		return mappedFmt
	}
	return timeFmt
}
func (n *Node) SetTime(tv, timeFmt string) (usedFmt string, err error) {
	timeFmt = NormTimeFormat(timeFmt)
	if !n.IsTime() {
		return timeFmt, errors.New("cannot set value because it is not of type time.Time")
	}
	t, err := time.Parse(timeFmt, tv)
	if err != nil {
		return timeFmt, err
	}
	n.SetStruct(t)
	return timeFmt, nil
}