- Use golang struct instead of map for config.
- Versioned and Atomic reloadable configuration
- Customizable decoders(json out of box)
- Customizable config source(reloadable file source out of box)
- Hooks in config lifecycle, and can be used to customize behavior of cfg package:
- PreDecoder: called before new config decoding from source. It can be used to set default value.
- PostDecoder: called after new config decoding from source. It can be used to validate new config.
- PostSwap: called after new config taked effect(implemented by atomic swap pointers). It can be used to notify that new config is reloaded.
- Simple logger interface to log events.
import (
validator "github.com/go-playground/validator/v10"
"github.com/gokits/cfg"
"github.com/gokits/cfg/source/file"
)
//...
// 1. define config struct
// 2. define validator(optional)
type Config struct {
MaxRetry int `validate:"min=0,max=10"`
LogPath string
}
var (
gvalidator *validator.Validate
filesource *file.File
meta *cfg.ConfigMeta
)
//...
// define PostDecode hook to validate new config. New config reload will be canceled if `error != nil`.
// `oldptr` will hold pointer to current version config struct
// `c` will hold pointer to new config struct
func (c *Config) PostDecode(oldptr interface{}) error {
return gvalidator.Struct(c)
}
//...
func main() {
gvalidator = validator.New()
if filesource, err = file.NewFileSource("./tmp.json"); err != nil {
return
}
defer filesource.Close()
meta = cfg.NewConfigMeta(Config{}, filesource)
go meta.Run()
if err = meta.WaitSynced(); err != nil {
return
}
fmt.Printf("%+v\n", meta.Get().(*Config))
}
- [done] reloadable file source
- [done] custimizable hooks
- [todo] export config version
- [todo] frozen package api and release v1
- [todo] implement other config source(etcd, consul...)
This package has been used in production environment running on our kubernetes clusters. It works well with configmap of kubernetes and files.