func (c *Ini) Section(name string) Section {
	return c.StringMap(name)
}
***********************************************************
section operate
***********************************************************
Section get a section data map. is alias of StringMap()
package ini
import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"github.com/mitchellh/mapstructure"
)
func GetValue(key string) (string, bool) { return dc.GetValue(key) }
func (c *Ini) GetValue(key string) (val string, ok bool) {
	if !c.opts.Readonly {
		c.lock.Lock()
		defer c.lock.Unlock()
	}
	if key = c.formatKey(key); key == "" {
		return
	}
	name, key := c.splitSectionAndKey(key)
	strMap, ok := c.data[name]
	if !ok {
		return
	}
	val, ok = strMap[key]
	if c.opts.ParseVar {
		if !c.opts.Readonly {
			c.lock.Unlock()
			val = c.parseVarReference(key, val, strMap)
			c.lock.Lock()
		} else {
			val = c.parseVarReference(key, val, strMap)
		}
	}
	if c.opts.ParseEnv {
		val = ParseEnvValue(val)
	}
	return
}
var envRegex = regexp.MustCompile(`\${.+?}`)
var EnvValueGetter = func(name string) string {
	return os.Getenv(name)
}
func ParseEnvValue(val string) (newVal string) {
	if strings.Index(val, "${") == -1 {
		return val
	}
	var name, def string
	return envRegex.ReplaceAllStringFunc(val, func(eVar string) string {
		ss := strings.SplitN(eVar[2:len(eVar)-1], "|", 2)
		if len(ss) == 2 {
			name, def = strings.TrimSpace(ss[0]), strings.TrimSpace(ss[1])
		} else {
			def = eVar  
			name = strings.TrimSpace(ss[0])
		}
		eVal := EnvValueGetter(name)
		if eVal == "" {
			eVal = def
		}
		return eVal
	})
}
func Get(key string, defVal ...string) string { return dc.Get(key, defVal...) }
func (c *Ini) Get(key string, defVal ...string) string {
	value, ok := c.GetValue(key)
	if !ok && len(defVal) > 0 {
		value = defVal[0]
	}
	return value
}
func String(key string, defVal ...string) string { return dc.String(key, defVal...) }
func (c *Ini) String(key string, defVal ...string) string {
	return c.Get(key, defVal...)
}
func Int(key string, defVal ...int) int { return dc.Int(key, defVal...) }
func (c *Ini) Int(key string, defVal ...int) (value int) {
	i64, exist := c.tryInt64(key)
	if exist {
		value = int(i64)
	} else if len(defVal) > 0 {
		value = defVal[0]
	}
	return
}
func Uint(key string, defVal ...uint) uint { return dc.Uint(key, defVal...) }
func (c *Ini) Uint(key string, defVal ...uint) (value uint) {
	i64, exist := c.tryInt64(key)
	if exist {
		value = uint(i64)
	} else if len(defVal) > 0 {
		value = defVal[0]
	}
	return
}
func Int64(key string, defVal ...int64) int64 { return dc.Int64(key, defVal...) }
func (c *Ini) Int64(key string, defVal ...int64) (value int64) {
	value, exist := c.tryInt64(key)
	if !exist && len(defVal) > 0 {
		value = defVal[0]
	}
	return
}
func (c *Ini) tryInt64(key string) (value int64, ok bool) {
	strVal, ok := c.GetValue(key)
	if !ok {
		return
	}
	value, err := strconv.ParseInt(strVal, 10, 0)
	if err != nil {
		c.err = err
	}
	return
}
func Bool(key string, defVal ...bool) bool { return dc.Bool(key, defVal...) }
func (c *Ini) Bool(key string, defVal ...bool) (value bool) {
	rawVal, ok := c.GetValue(key)
	if !ok {
		if len(defVal) > 0 {
			return defVal[0]
		}
		return
	}
	lowerCase := strings.ToLower(rawVal)
	switch lowerCase {
	case "", "0", "false", "no", "off":
		value = false
	case "1", "true", "yes", "on":
		value = true
	default:
		c.addErrorf("the value '%s' cannot be convert to bool", lowerCase)
	}
	return
}
func Strings(key string, sep ...string) []string { return dc.Strings(key, sep...) }
func (c *Ini) Strings(key string, sep ...string) (ss []string) {
	str, ok := c.GetValue(key)
	if !ok {
		return
	}
	if len(sep) > 0 {
		return stringToArray(str, sep[0])
	}
	return stringToArray(str, ",")
}
func StringMap(name string) map[string]string { return dc.StringMap(name) }
func (c *Ini) StringMap(name string) (mp map[string]string) {
	name = c.formatKey(name)
	if name == "" {
		name = c.opts.DefSection
	}
	mp, ok := c.data[name]
	if !ok {
		return
	}
	if c.opts.ParseVar {
		for k, v := range mp {
			mp[k] = c.parseVarReference(k, v, mp)
		}
	}
	if c.opts.ParseEnv {
		for k, v := range mp {
			mp[k] = ParseEnvValue(v)
		}
	}
	return
}
func MapStruct(key string, ptr interface{}) error { return dc.MapStruct(key, ptr) }
func (c *Ini) MapStruct(key string, ptr interface{}) error {
	if key == "" {
		defSec := c.opts.DefSection
		if defMap, ok := c.data[defSec]; ok {
			data := make(map[string]interface{}, len(defMap)+len(c.data)-1)
			for key, val := range defMap {
				data[key] = val
			}
			for secKey, secVals := range c.data {
				if secKey != defSec {
					data[secKey] = secVals
				}
			}
			return mapStruct(c.opts.TagName, data, ptr)
		}
		return mapStruct(c.opts.TagName, c.data, ptr)
	}
	data := c.StringMap(key)
	if len(data) == 0 {
		return errNotFound
	}
	return mapStruct(c.opts.TagName, data, ptr)
}
func mapStruct(tagName string, data interface{}, ptr interface{}) error {
	mapConf := &mapstructure.DecoderConfig{
		Metadata: nil,
		Result:   ptr,
		TagName:  tagName,
		WeaklyTypedInput: true,
	}
	decoder, err := mapstructure.NewDecoder(mapConf)
	if err != nil {
		return err
	}
	return decoder.Decode(data)
}
func Set(key string, val interface{}, section ...string) error {
	return dc.Set(key, val, section...)
}
func (c *Ini) Set(key string, val interface{}, section ...string) (err error) {
	if c.opts.Readonly {
		return errReadonly
	}
	c.ensureInit()
	c.lock.Lock()
	defer c.lock.Unlock()
	key = c.formatKey(key)
	if key == "" {
		return errEmptyKey
	}
	name := c.opts.DefSection
	if len(section) > 0 {
		name = section[0]
	}
	strVal, isString := val.(string)
	if !isString {
		strVal = fmt.Sprint(val)
	}
	name = c.formatKey(name)
	sec, ok := c.data[name]
	if ok {
		sec[key] = strVal
	} else {
		sec = Section{key: strVal}
	}
	c.data[name] = sec
	return
}
func (c *Ini) PrettyJSON() string {
	if len(c.data) == 0 {
		return ""
	}
	out, _ := json.MarshalIndent(c.data, "", "    ")
	return string(out)
}
func (c *Ini) WriteToFile(file string) (int64, error) {
	fd, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0664)
	if err != nil {
		return 0, err
	}
	return c.WriteTo(fd)
}
func (c *Ini) WriteTo(out io.Writer) (n int64, err error) {
	n = 0
	counter := 0
	thisWrite := 0
	defaultSection := c.opts.DefSection
	orderedSections := make([]string, len(c.data))
	for section := range c.data {
		orderedSections[counter] = section
		counter++
	}
	sort.Strings(orderedSections)
	for _, section := range orderedSections {
		if section != defaultSection {
			thisWrite, err = fmt.Fprintln(out, "["+section+"]")
			n += int64(thisWrite)
			if err != nil {
				return
			}
		}
		items := c.data[section]
		orderedStringKeys := make([]string, len(items))
		counter = 0
		for key := range items {
			orderedStringKeys[counter] = key
			counter++
		}
		sort.Strings(orderedStringKeys)
		for _, key := range orderedStringKeys {
			thisWrite, err = fmt.Fprintln(out, key, "=", items[key])
			n += int64(thisWrite)
			if err != nil {
				return
			}
		}
		thisWrite, err = fmt.Fprintln(out)
		n += int64(thisWrite)
		if err != nil {
			return
		}
	}
	return
}