Config
config
- Simple, full-featured Go application configuration management tool library.
中文说明
Features
- Support multi format:
JSON
(default), JSON5
, INI
, Properties
, YAML
, TOML
, HCL
, ENV
, Flags
JSON
content support comments. will auto clear comments- Other drivers are used on demand, not used will not be loaded into the application.
- Possibility to add custom driver for your specific format
- Support multi-file and multi-data loading
- Support for loading configuration from system ENV
- Support for loading configuration data from remote URLs
- Support for setting configuration data from command line(
flags
) - Support listen and fire events on config data changed.
- allow events:
set.value
, set.data
, load.data
, clean.data
, reload.data
- Support data overlay and merge, automatically load by key when loading multiple copies of data
- Support for binding all or part of the configuration data to the structure
- Support init default value by struct tag
default:"def_value"
- Support init default value from ENV
default:"${APP_ENV | dev}"
- Support get sub value by key-path, like
map.key
arr.2
- Support parse ENV name and allow with default value. like
envKey: ${SHELL|/bin/bash}
-> envKey: /bin/zsh
- Generic API:
Get
Int
Uint
Int64
Float
String
Bool
Ints
IntMap
Strings
StringMap
... - Complete unit test(code coverage > 95%)
Only use INI
If you just want to use INI for simple config management, recommended use gookit/ini
Load dotenv file
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/dotenv
GoDoc
Install
go get github.com/gookit/config/v2
Usage
Here 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
- val21
Load data
examples code please see _examples/yaml.go:
package main
import (
"github.com/gookit/config/v2"
"github.com/gookit/config/v2/yaml"
)
func main() {
config.WithOptions(config.ParseEnv)
config.AddDriver(yaml.Driver)
err := config.LoadFiles("testdata/yml_base.yml")
if err != nil {
panic(err)
}
err = config.LoadFiles("testdata/yml_other.yml")
if err != nil {
panic(err)
}
}
Usage tips:
- More extra options can be added using
WithOptions()
. For example: ParseEnv
, ParseDefault
- You can use
AddDriver()
to add the required format driver (json
is loaded by default, no need to add) - The configuration data can then be loaded using
LoadFiles()
LoadStrings()
etc.
- You can pass in multiple files or call multiple times
- Data loaded multiple times will be automatically merged by key
Bind Structure
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)
Change struct tag name
config.WithOptions(func(opt *Options) {
options.DecoderConfig.TagName = "config"
})
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)
config.BindStruct("", &myConf)
config.MapOnExists
like BindStruct
,but map binding only if key exists
Direct read data
age := config.Int("age")
fmt.Print(age)
val := config.Bool("debug")
fmt.Print(val)
name := config.String("name")
fmt.Print(name)
arr1 := config.Strings("arr1")
fmt.Printf("%#v", arr1)
val := config.StringMap("map1")
fmt.Printf("%#v",val)
value := config.String("shell")
fmt.Print(value)
value := config.String("arr1.0")
fmt.Print(value)
value := config.String("map1.key")
fmt.Print(value)
config.Set("name", "new name")
name = config.String("name")
fmt.Print(name)
Load from flags
Support simple flags parameter parsing, loading
keys := []string{"name", "env", "age:int" "debug:bool"}
err := config.LoadFlags(keys)
config.String("name")
config.String("env")
config.Int("age")
config.Bool("debug")
Load from ENV
config.LoadOSEnvs(map[string]string{"APP_NAME": "app_name", "APP_DEBUG": "app_debug"})
config.Bool("app_debug")
config.String("app_name")
New config instance
You can create custom config instance
myConf := config.New("my-conf")
myConf := config.NewEmpty("my-conf")
myConf := config.NewWithOptions("my-conf", config.ParseEnv, config.ReadOnly)
Listen config change
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))
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
Watch loaded config files
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 ./_example/watch_file.go
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.
Dump config data
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)
Available options
type Options struct {
ParseEnv bool
ParseTime bool
Readonly bool
EnableCache bool
ParseKey bool
Delimiter byte
DumpFormat string
ReadFormat string
DecoderConfig *mapstructure.DecoderConfig
HookFunc HookFunc
ParseDefault bool
}
Examples for set options:
config.WithOptions(config.WithTagName("mytag"))
config.WithOptions(func(opt *Options) {
opt.SetTagNames("config")
})
Options: Parse default
Support parse default value by struct tag default
c := config.New("test").WithOptions(config.ParseDefault)
c.SetData(map[string]any{
"name": "inhere",
})
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
],
},
API Methods Refer
Load Config
LoadOSEnvs(nameToKeyMap map[string]string)
Load data from os ENVLoadData(dataSource ...any) (err error)
Load from struts or mapsLoadFlags(keys []string) (err error)
Load from CLI flagsLoadExists(sourceFiles ...string) (err error)
LoadFiles(sourceFiles ...string) (err error)
LoadFromDir(dirPath, format string) (err error)
Load custom format files from the given directory, the file name will be used as the keyLoadRemote(format, url string) (err error)
LoadSources(format string, src []byte, more ...[]byte) (err error)
LoadStrings(format string, str string, more ...string) (err error)
LoadFilesByFormat(format string, sourceFiles ...string) (err error)
LoadExistsByFormat(format string, sourceFiles ...string) error
Getting Values
Bool(key string, defVal ...bool) bool
Int(key string, defVal ...int) int
Uint(key string, defVal ...uint) uint
Int64(key string, defVal ...int64) int64
Ints(key string) (arr []int)
IntMap(key string) (mp map[string]int)
Float(key string, defVal ...float64) float64
String(key string, defVal ...string) string
Strings(key string) (arr []string)
SubDataMap(key string) maputi.Data
StringMap(key string) (mp map[string]string)
Get(key string, findByPath ...bool) (value any)
Mapping data to struct:
Decode(dst any) error
BindStruct(key string, dst any) error
MapOnExists(key string, dst any) error
Setting Values
Set(key string, val any, setByPath ...bool) (err error)
Useful Methods
Getenv(name string, defVal ...string) (val string)
AddDriver(driver Driver)
Data() map[string]any
SetData(data map[string]any)
set data to override the Config.DataExists(key string, findByPath ...bool) bool
DumpTo(out io.Writer, format string) (n int64, err error)
Run Tests
go test -cover
// contains all sub-folder
go test -cover ./...
Projects using config
Check out these projects, which use https://github.com/gookit/config :
Gookit packages
- gookit/ini Go config management, use INI files
- gookit/rux Simple and fast request router for golang HTTP
- gookit/gcli build CLI application, tool library, running CLI commands
- gookit/event Lightweight event manager and dispatcher implements by Go
- gookit/cache Generic cache use and cache manager for golang. support File, Memory, Redis, Memcached.
- gookit/config Go config management. support JSON, YAML, TOML, INI, HCL, ENV and Flags
- gookit/color A command-line color library with true color support, universal API methods and Windows support
- gookit/filter Provide filtering, sanitizing, and conversion of golang data
- gookit/validate Use for data validation and filtering. support Map, Struct, Form data
- gookit/goutil Some utils for the Go: string, array/slice, map, format, cli, env, filesystem, test and more
- More, please see https://github.com/gookit
See also
License
MIT