项目作者: ysugimoto

项目描述 :
Cascade and integrate config struct from various setting files and environment.
高级语言: Go
项目地址: git://github.com/ysugimoto/twist.git
创建时间: 2019-05-07T14:54:15Z
项目社区:https://github.com/ysugimoto/twist

开源协议:MIT License

下载


GoDoc

twist

Cascade and integrate config struct from various setting files, envrironments, and command-line arguments

Supporting configuration types:

  • toml file
  • yaml file
  • json file
  • ini file
  • environment variables
  • command-line arguments
  • default values

Installation

  1. $ go get -u github.com/ysugimoto/twist

Or install via package manager which you’re using like dep, go mod, etc…

Getting Started

Define your configuration strcut and call Mix() function with cascading configurations.

Here is toml file example:

  1. # /path/to/setting.toml
  2. host = "localhost"
  3. port = 8000
  4. [service]
  5. name = "My Service"
  6. description = "This is my favorite service"

Then this package can use as following:

  1. package main
  2. import (
  3. "log"
  4. "github.com/ysugimoto/twist"
  5. )
  6. type MyConfig struct {
  7. Host string `toml:"host"`
  8. Port int `toml:"port"`
  9. Service struct{
  10. Name string `toml:"name"`
  11. Description string `toml:"description"`
  12. } `toml:"service"` // <- need this
  13. }
  14. func main() {
  15. var config MyConfig
  16. if err := twist.Mix(&config, twist.WithToml("/path/to/setting.toml")); err != nil {
  17. log.Fatal(err)
  18. }
  19. log.Println(config.Host) // => localhost
  20. log.Println(config.Port) // => 8000
  21. log.Println(config.Service.Name) // => My Service
  22. log.Println(config.Service.Description) // => This is my favorite service
  23. }

Merging configuration from various kind of files and defaults

This package can support kinds of config files (eg. yaml and json and env).
To merge from some configurations, call Mix() with some of WithXXX options and make sure put tag in your struct field which you want to assign:

  1. package main
  2. import (
  3. "log"
  4. "os"
  5. "github.com/ysugimoto/twist"
  6. )
  7. type MyConfig struct {
  8. Host string `toml:"host"` // will be used from toml file
  9. Port int `yaml:"port"` // will be used from yaml file
  10. Service struct{
  11. Name string `default:"My Service"` // set as default
  12. Description string `default:"My Favorite Service"` // set as default
  13. } `toml:"service" yaml:"service"` // <- need if you want to assign from multiple files
  14. Secret string `env:"SECRET"` // will be used from envrironment variable
  15. }
  16. func main() {
  17. var config MyConfig
  18. if err := twist.Mix(
  19. &config,
  20. twist.WithToml("/path/to/setting.toml"),
  21. twist.WithToml("/path/to/setting.yaml"),
  22. twist.WithEnv(),
  23. ); err != nil {
  24. log.Fatal(err)
  25. }
  26. log.Println(config.Host) // => host in toml file
  27. log.Println(config.Port) // => port in yaml file
  28. log.Println(config.Service.Name) // => My Service as default
  29. log.Println(config.Service.Description) // => My Favorite Service as default
  30. log.Println(config.Secret) // => value of os.Getenv("SECRET")
  31. }

Of course you’ll confuse when cascading from different file types, so usually you can use from same file of partial configurations and integrate it, and secret values (like accessToken, etc) should be assigned from envrironment variables:

  1. # /path/to/server.json
  2. {
  3. "host": "localhost",
  4. "port": 8000
  5. }
  6. # /path/to/service.json
  7. {
  8. "service": {
  9. "name": "My Service",
  10. "description": "My Favorite Service"
  11. }
  12. }

Then cascading is:

  1. package main
  2. import (
  3. "log"
  4. "github.com/ysugimoto/twist"
  5. )
  6. type MyConfig struct {
  7. Host string `json:"host"`
  8. Port int `json:"port"`
  9. Service struct{
  10. Name string `json:"name"`
  11. Description string `json:"description"`
  12. } `json:"service"`
  13. Secret string `env:"SECRET"` // will be used from envrironment variable
  14. Verbose string `cli:"v,verbose"` // will be used from command-line arguments
  15. }
  16. func main() {
  17. var config MyConfig
  18. if err := twist.Mix(
  19. &config,
  20. twist.WithToml("/path/to/server.json"), // will set only Host and Port
  21. twist.WithToml("/path/to/service.json"), // will set only Service.Name and Service.Description
  22. twist.WithEnv(),
  23. twist.WithCli(os.Args[1:]),
  24. ); err != nil {
  25. log.Fatal(err)
  26. }
  27. log.Println(config.Host) // => host value in server.json
  28. log.Println(config.Port) // => port value in server.json
  29. log.Println(config.Service.Name) // => name value in service.json
  30. log.Println(config.Service.Description) // => description value in service.json
  31. log.Println(config.Secret) // => value of os.Getenv("SECRET")
  32. }

Correspond Struct Tags

  1. type Config struct {
  2. TomlValue string `toml:"value"` // for toml mapping
  3. YamlValue string `yaml:"value"` // for yaml mapping
  4. JsonValue string `json:"value"` // for json mapping
  5. IniValue string `ini:"value"` // for ini mapping
  6. EnvValue string `env:"ENV_NAME"` // for env mapping
  7. CliValue string `cli:"short,long"` // for cli mapping
  8. DefaultValue string `default:"value"` // set as default value
  9. }

toml, yaml, json and ini are used following packages:

  • github.com/BurntSushi/toml
  • github.com/go-yaml/yaml
  • github.com/go-ini/ini
  • encoding/json

env and cli is package defined.

Author

Yoshiaki Sugimoto

License

MIT

PR is welcome :-)