| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
config - Simple, full-featured Go application configuration management tool library.
If you just want to use INI for simple config management, recommended use gookit/ini
On gookit/ini: Provide a sub-package dotenv that supports importing data from files (eg .env) to ENV
go get github.com/gookit/ini/v2/dotenvgo get github.com/gookit/config/v2Here using the yaml format as an example(testdata/yml_other.yml):
name: app2
debug: false
baseKey: value2
shell: ${SHELL}
envKey1: ${NotExist|defValue}
map1:
key: val2
key2: val20
arr1:
- val1
- val21examples code please see _examples/yaml.go:
package main
import (
"github.com/gookit/config/v2"
"github.com/gookit/config/v2/yaml"
)
// go run ./examples/yaml.go
func main() {
// config.ParseEnv: will parse env var in string value. eg: shell: ${SHELL}
config.WithOptions(config.ParseEnv)
// add driver for support yaml content
config.AddDriver(yaml.Driver)
err := config.LoadFiles("testdata/yml_base.yml")
if err != nil {
panic(err)
}
// load more files
err = config.LoadFiles("testdata/yml_other.yml")
// can also load multi at once
// err := config.LoadFiles("testdata/yml_base.yml", "testdata/yml_other.yml")
if err != nil {
panic(err)
}
// fmt.Printf("config data: \n %#v\n", config.Data())
}Usage tips:
Note: The default binding mapping tag of a structure is mapstructure, which can be changed by setting the decoder's option options.DecoderConfig.TagName
type User struct {
Age int `mapstructure:"age"`
Key string `mapstructure:"key"`
UserName string `mapstructure:"user_name"`
Tags []int `mapstructure:"tags"`
}
user := User{}
err = config.BindStruct("user", &user)
fmt.Println(user.UserName) // inhereChange struct tag name
config.WithOptions(func(opt *Options) {
options.DecoderConfig.TagName = "config"
})
// use custom tag name.
type User struct {
Age int `config:"age"`
Key string `config:"key"`
UserName string `config:"user_name"`
Tags []int `config:"tags"`
}
user := User{}
err = config.Decode(&user)Can bind all config data to a struct:
config.Decode(&myConf)
// can also
config.BindStruct("", &myConf)config.MapOnExists like BindStruct,but map binding only if key exists
age := config.Int("age")
fmt.Print(age) // 100val := config.Bool("debug")
fmt.Print(val) // truename := config.String("name")
fmt.Print(name) // inherearr1 := config.Strings("arr1")
fmt.Printf("%#v", arr1) // []string{"val1", "val21"}val := config.StringMap("map1")
fmt.Printf("%#v",val) // map[string]string{"key":"val2", "key2":"val20"}value := config.String("shell")
fmt.Print(value) // "/bin/zsh"// from array
value := config.String("arr1.0")
fmt.Print(value) // "val1"
// from map
value := config.String("map1.key")
fmt.Print(value) // "val2"// set value
config.Set("name", "new name")
name = config.String("name")
fmt.Print(name) // "new name"Support load ENV vars to config data.
// os env: APP_NAME=config APP_DEBUG=true DB_USERNAME=someone
// load ENV info
config.LoadOSEnvs(map[string]string{"APP_NAME": "app_name", "APP_DEBUG": "app_debug", "DB_USERNAME": "db.username"})
// read
config.Bool("app_debug") // true
config.String("app_name") // "config"Support simple CLI flags parameter parsing, load to config data.
// 'debug' flag is bool type
config.LoadFlags([]string{"env", "debug:bool"})
// can with flag desc message
config.LoadFlags([]string{"env:set the run env"})
config.LoadFlags([]string{"debug:bool:set debug mode"})
// can set value to map key. eg: myapp --map1.sub-key=val
config.LoadFlags([]string{"map1.sub-key"})Examples:
// flags like: --name inhere --env dev --age 99 --debug --map1.sub-key=val
// load flag info
keys := []string{
"name",
"env:set the run env",
"age:int",
"debug:bool:set debug mode",
"map1.sub-key",
}
err := config.LoadFlags(keys)
// read
config.String("name") // "inhere"
config.String("env") // "dev"
config.Int("age") // 99
config.Bool("debug") // true
config.Get("map1") // map[string]any{"sub-key":"val"}You can create custom config instance
// create new instance, will auto register JSON driver
myConf := config.New("my-conf")
// create empty instance
myConf := config.NewEmpty("my-conf")
// default add options: ParseEnv, ParseDefault, ParseTime
myConf := config.NewGeneric("my-conf")
// create and with some options
myConf := config.NewWithOptions("my-conf", config.ParseEnv, config.ReadOnly)Now, you can add a hook func for listen config data change. then, you can do something like: write data to file
Add hook func on create config:
hookFn := func(event string, c *Config) {
fmt.Println("fire the:", event)
}
c := NewWithOptions("test", config.WithHookFunc(hookFn))
// for global config
config.WithOptions(config.WithHookFunc(hookFn))After that, when calling LoadXXX, Set, SetData, ClearData methods, it will output:
fire the: load.data
fire the: set.value
fire the: set.data
fire the: clean.data
To listen for changes to loaded config files, and reload the config when it changes, you need to use the https://github.com/fsnotify/fsnotify library. For usage, please refer to the example ./_examples/watch_file.go
Note: editors may emit multiple WRITE events while saving, and the file content may not be fully written when the event is received. Use a short debounce, as shown in the example, before calling ReloadFiles().
Also, you need to listen to the reload.data event:
config.WithOptions(config.WithHookFunc(func(event string, c *config.Config) {
if event == config.OnReloadData {
fmt.Println("config reloaded, you can do something ....")
}
}))When the configuration changes, you can do related things, for example: rebind the configuration to your struct.
Can use config.DumpTo() export the configuration data to the specified writer, such as: buffer,file
Dump to JSON file
buf := new(bytes.Buffer)
_, err := config.DumpTo(buf, config.JSON)
ioutil.WriteFile("my-config.json", buf.Bytes(), 0755)Dump pretty JSON
You can set the default var JSONMarshalIndent or custom a new JSON driver.
config.JSONMarshalIndent = " "Dump to YAML file
_, err := config.DumpTo(buf, config.YAML)
ioutil.WriteFile("my-config.yaml", buf.Bytes(), 0755)// Options config options
type Options struct {
// parse env in string value. like: "${EnvName}" "${EnvName|default}"
ParseEnv bool
// ParseTime parses a duration string to time.Duration
// eg: 10s, 2m
ParseTime bool
// config is readonly. default is False
Readonly bool
// enable config data cache. default is False
EnableCache bool
// parse key, allow find value by key path. default is True eg: 'key.sub' will find `map[key]sub`
ParseKey bool
// the delimiter char for split key path, if `FindByPath=true`. default is '.'
Delimiter byte
// default write format
DumpFormat string
// default input format
ReadFormat string
// DecoderConfig setting for binding data to struct
DecoderConfig *mapstructure.DecoderConfig
// HookFunc on data changed.
HookFunc HookFunc
// ParseDefault tag on binding data to struct. tag: default
ParseDefault bool
}TIP: please visit https://pkg.go.dev/github.com/gookit/config/v2#Options to see the latest options information
Examples for set options:
config.WithOptions(config.WithTagName("mytag"))
config.WithOptions(func(opt *Options) {
opt.SetTagNames("config")
})Support parse default value by struct tag default, and support parse fields in sub struct.
NOTE⚠️ If you want to parse a sub-struct, you need to set the default:"" flag on the parent struct, otherwise the fields of the sub-struct will not be resolved.
// add option: config.ParseDefault
c := config.New("test").WithOptions(config.ParseDefault)
// only set name
c.SetData(map[string]any{
"name": "inhere",
})
// age load from default tag
type User struct {
Age int `default:"30"`
Name string
Tags []int
}
user := &User{}
goutil.MustOk(c.Decode(user))
dump.Println(user)Output:
&config_test.User {
Age: int(30),
Name: string("inhere"), #len=6
Tags: []int [ #len=0
],
},Mapping data to struct:
go test -cover
// contains all sub-folder
go test -cover ./...MIT
| Back | FazBrowse Home | New Git URL |