Documentation ¶
Overview ¶
Package config implements a model based config system for your app. It's based on Viper. Instead of using Viper's Get and Set, this package binds all config to a struct, and you can get values by codes like
fmt.Println(Config.Foo.Bar)
This structured config makes it easy and straightforward to get config values. And it's also avoiding viper's string problems:
Get("typo"): it's annoying to debug typos in strings. Compiler do nothing to make sure you are getting a right value. You can only find those issues at runtime as unexpected empty value errors.
We have no place (inside the project) to see what configs are required and what types they are. I heat writing codes with a sample config file aside.
You can use config.Init to read (and watch) config from file or environment variables and bind it to a struct.
This package also provides a BaseConfig struct, which is a base struct for common configs can be applied in a crud app. It's a good idea to embed it in your own config struct.
Example:
type MyConfig struct { BaseConfig `mapstructure:",squash"` Foo string Bar int } var config MyConfig err := Init(&config, FromFile("./test_config.yaml"), // read config from file FromEnv("MYAPP"), // read config from env with prefix MYAPP, for example MYAPP_FOO, MYAPP_DB_DSN WatchFileChange(func(oldConfig any, newConfig any) { // only file changes are watched, env changes will not trigger. logger.WithField("oldConfig", oldConfig). WithField("newConfig", newConfig). Info("config changed") }), ) if err != nil { logger.WithError(err).Fatal("failed to read config.") }
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrConfigNotPtrToStruct = errors.New("config must be a pointer to struct")
Functions ¶
func Init ¶
Init reads configure, write values into given configModel
- FromFile: read config from file
- FromEnv: read config from environment variables
- WatchFileChange: watch config file and reload config when changed
Example ¶
type MyConfig struct { BaseConfig `mapstructure:",squash"` Foo string Bar int } var config MyConfig err := Init(&config, FromFile("./test_config.yaml"), FromEnv("MYAPP"), WatchFileChange(func(oldConfig any, newConfig any) { logger.WithField("oldConfig", oldConfig). WithField("newConfig", newConfig). Info("config changed") }), ) if err != nil { logger.WithError(err).Fatal("failed to read config.") }
Output:
Types ¶
type BaseConfig ¶
type BaseConfig struct { DB DBConfig // database config HTTP HTTPConfig // http listen config LogLevel string // log level }
BaseConfig includes common config for services
type DBConfig ¶
type DBConfig struct { Driver string // db driver name: sqlite, mysql, postgres DSN string // db connection string }
DBConfig is the configurations for connecting database
type HTTPConfig ¶
type HTTPConfig struct {
Addr string // listen address: ":8080"
}
HTTPConfig is the configurations for HTTP server
type Option ¶
func FromEnv ¶
FromEnv reads config from environment variables, and unmarshal to config prefix is the prefix of environment variables:
type MyConfig struct { Foo struct { Bar string } } config := MyConfig{} config.Init(&config, FromEnv("MYAPP"))
will read `config.Foo.Bar` from env `MYAPP_FOO_BAR`.
func FromFile ¶
FromFile reads config from file at path, and unmarshal to config. YAML, JSON, TOML, etc. files are supported. This is the recommended way to read config.
func WatchFileChange ¶
WatchFileChange works with FromFile:
var config MyConfig config.Init(&config, FromFile(path), WatchFileChange(hook))
WatchFileChange watch current viper config file, and reload config when changed.
Notice: you do not need to reset your `config` variable in the hook, we will do it for you. BUT THIS FEATURE MAKE THE `config` NOT THREAD-SAFE. It's to be fixed in the future.