My go-to Go package for my Go apps, based on my highly specific and opinionated configuration needs.
Built upon github.com/spf13/viper
It's probably not for everyone.
Been using spf13/viper for a while now, and I've been using it in a very specific way in many of my Go projects.
Instead of creating a new internal config package everytime, I decided to create a single package that I can use in all my projects.
This package might be a perfect match for your needs, or perhaps not quite. Either way, feel free to give it a try or pass it by.
Suggestions and feedback are always appreciated.
go get github.com/sogko/config
Right out of the box, the package expects a config.dev.json
file relative to the current working directory.
{
"foo": "bar"
}
package main
import (
"fmt"
"github.com/sogko/config"
)
func main() {
// Load configuration
cfg := config.Load()
// Get configuration value
foo := cfg.GetString("foo")
// Print configuration value
fmt.Printf("foo: %s\n", foo)
// Output: foo: bar
}
The package expects a configuration file in JSON format.
The package expects a configuration file named config.<environment>.json
.
By default, the environment is set to dev
(i.e. it will look for config.dev.json
file).
By setting the ENV
environment variable, you can change the environment to prod
or staging
or whatever you want,
and the package will look for config.prod.json
file, or config.staging.json
file, etc.
You can also set the CONFIG
environment variable to specify the name and location of the configuration file (accepts both relative and absolute paths).
The package expects a configuration file to exist in the current working directory.
You can also set the CONFIG
environment variable to specify the location of the configuration file (accepts both relative and absolute paths).
CONFIG
: Configuration file pathENV
: EnvironmentENV_PREFIX
: Environment variable prefix
Default: <not set>
Accepts both relative and absolute paths.
For relative paths, it is relative to the current working directory.
// Default: config.dev.json
{
"foo": "bar"
}
// Relative path: ./my_custom_config.json
{
"foo": "custom_bar"
}
// Absolute path: /User/alice/config.prod.json
{
"foo": "barber"
}
func main() {
cfg := config.Load()
fmt.Printf("foo: %s\n", cfg.GetString("foo"))
}
$ go run main.go
# Output: foo: bar
$ env CONFIG=./my_custom_config go run main.go
# Output: foo: custom_bar
$ env CONFIG=/User/alice/config.prod.json go run main.go
# Output: foo: barber
Default: dev
Alias: ENVIRONMENT
Here's an example of setting the environment to prod
via ENV
environment variable.
// config.dev.json
{
"foo": "bar"
}
// config.prod.json
{
"foo": "barber"
}
func main() {
cfg := config.Load()
fmt.Printf("foo: %s\n", cfg.GetString("foo"))
}
$ go run main.go
# Output: foo: bar
$ env ENV=dev go run main.go
# Output: foo: bar
$ env ENV=prod go run main.go
# Output: foo: barber
Default: <not set>
You can set a prefix for your environment variables via ENV_PREFIX
,
so that they don't conflict with other apps.
By default, it is not set.
Here's a basic example of how you can set ENV_PREFIX
to MYAPP
and then set MYAPP_FOO
environment variable to barber
.
Note that environment variables takes precedence over config file values.
// config.dev.json
{
"foo": "bar"
}
func main() {
cfg := config.Load()
fmt.Printf("foo: %s\n", cfg.GetString("foo"))
}
$ env ENV_PREFIX=MYAPP MYAPP_FOO=barber go run main.go
# Output: foo: barber
$ env ENV_PREFIX=OTHERAPP OTHERAPP_FOO=barber go run main.go
# Output: foo: barber
Once ENV_PREFIX
is set, the built-in environment keys (ENV
and CONFIG
) will be prefixed as well.
// config.dev.json
{
"foo": "bar"
}
// config.prod.json
{
"foo": "barber"
}
func main() {
cfg := config.Load()
fmt.Printf("foo: %s\n", cfg.GetString("foo"))
}
$ env ENV_PREFIX=MYAPP MYAPP_ENV=prod go run main.go
# Output: foo: barber
$ env ENV_PREFIX=MYAPP MYAPP_CONFIG=./config.prod.json go run main.go
# Output: foo: barber
In addition to github.com/spf13/viper API, the package also exposes the following methods:
Loads configuration from file and environment variables.
func main() {
// Load configuration
cfg := config.Load()
fmt.Printf("foo: %s\n", cfg.GetString("foo"))
// Output: foo: bar
}
Reloads configuration from file and environment variables.
This is useful if you want to manually reload configuration after changing the configuration file.
Watches for changes in the configuration file and reloads configuration when changes are detected.
Returns the path of the configuration file.
Wraps viper.Viper
struct.
All of Viper API methods are available.
Saves a configuration value to the configuration file.
Note: this method calls cfg.WriteConfig()
internally, which will overwrite the configuration file and writes all configuration keys and its values.