func Register(flagSetName string, set *flag.FlagSet) {
	flags[flagSetName] = set
}
Registers a flag set to be parsed. Register all flag sets
before calling this function. flag.CommandLine is automatically
registered.
package globalconf
import (
	"flag"
	"io/ioutil"
	"os"
	"os/user"
	"path"
	"strings"
	ini "github.com/rakyll/goini"
)
const (
	defaultConfigFileName = "config.ini"
)
var flags map[string]*flag.FlagSet = make(map[string]*flag.FlagSet)
type GlobalConf struct {
	Filename  string
	EnvPrefix string
	dict      *ini.Dict
}
type Options struct {
	Filename  string
	EnvPrefix string
}
func NewWithOptions(opts *Options) (g *GlobalConf, err error) {
	Register("", flag.CommandLine)
	var dict ini.Dict
	if opts.Filename != "" {
		dict, err = ini.Load(opts.Filename)
		if err != nil {
			return nil, err
		}
	} else {
		dict = make(ini.Dict, 0)
	}
	return &GlobalConf{
		Filename:  opts.Filename,
		EnvPrefix: opts.EnvPrefix,
		dict:      &dict,
	}, nil
}
func New(appName string) (g *GlobalConf, err error) {
	var u *user.User
	if u, err = user.Current(); u == nil {
		return
	}
	dirPath := path.Join(u.HomeDir, ".config", appName)
	if err = os.MkdirAll(dirPath, 0755); err != nil {
		return
	}
	filePath := path.Join(dirPath, defaultConfigFileName)
	if _, err = os.Stat(filePath); err != nil {
		if !os.IsNotExist(err) {
			return
		}
		if err = ioutil.WriteFile(filePath, []byte{}, 0644); err != nil {
			return
		}
	}
	opts := Options{Filename: filePath}
	return NewWithOptions(&opts)
}
func (g *GlobalConf) Set(flagSetName string, f *flag.Flag) error {
	g.dict.SetString(flagSetName, f.Name, f.Value.String())
	if g.Filename != "" {
		return ini.Write(g.Filename, g.dict)
	}
	return nil
}
func (g *GlobalConf) Delete(flagSetName, flagName string) error {
	g.dict.Delete(flagSetName, flagName)
	if g.Filename != "" {
		return ini.Write(g.Filename, g.dict)
	}
	return nil
}
func (g *GlobalConf) ParseSet(flagSetName string, set *flag.FlagSet) {
	set.VisitAll(func(f *flag.Flag) {
		val := getEnv(g.EnvPrefix, flagSetName, f.Name)
		if val != "" {
			set.Set(f.Name, val)
			return
		}
		val, found := g.dict.GetString(flagSetName, f.Name)
		if found {
			set.Set(f.Name, val)
		}
	})
}
func (g *GlobalConf) Parse() {
	for name, set := range flags {
		alreadySet := make(map[string]bool)
		set.Visit(func(f *flag.Flag) {
			alreadySet[f.Name] = true
		})
		set.VisitAll(func(f *flag.Flag) {
			if alreadySet[f.Name] {
				return
			}
			val := getEnv(g.EnvPrefix, name, f.Name)
			if val != "" {
				set.Set(f.Name, val)
				return
			}
			val, found := g.dict.GetString(name, f.Name)
			if found {
				set.Set(f.Name, val)
			}
		})
	}
}
func (g *GlobalConf) ParseAll() {
	if !flag.Parsed() {
		flag.Parse()
	}
	g.Parse()
}
func getEnv(envPrefix, flagSetName, flagName string) string {
	if envPrefix == "" {
		return ""
	}
	if flagSetName != "" {
		flagSetName += "_"
	}
	flagName = strings.Replace(flagName, ".", "_", -1)
	flagName = strings.Replace(flagName, "-", "_", -1)
	envKey := strings.ToUpper(envPrefix + flagSetName + flagName)
	return os.Getenv(envKey)
}