This project is a Go library for reading configuration data from various sources such as environment variables, command-line flags, and configuration files. The library provides a unified interface for reading configuration data, making it easier to manage and maintain your application's configuration.
The library uses the env, pflag, yaml, toml and godotenv codebase to work with environment variables and flags. This is a temporary solution, maybe I’ll write my own implementation later. Thanks to the authors of these libraries for the work done!
To install the library, use the go get command:
go get github.com/dsbasko/go-cfg
The library provides several functions for reading configuration data:
ReadEnv(cfg any) error
: Reads environment variables into the providedcfg
structure. Each field in thecfg
structure represents an environment variable.MustReadEnv(cfg any)
: Similar toReadEnv
but panics if the reading process fails.ReadFlag(cfg any) error
: Reads command-line flags into the providedcfg
structure. Each field in thecfg
structure represents a command-line flag.MustReadFlag(cfg any)
: Similar toReadFlag
but panics if the reading process fails.ReadFile(path string, cfg any) error
: Reads configuration from a file into the providedcfg
structure. The path parameter is the path to the configuration file. Each field in thecfg
structure represents a configuration option. Supported file formats include JSON, YAML, TOML and .env.MustReadFile(path string, cfg any)
: Similar toReadFile
but panics if the reading process fails.
Here is an example of how to use the library:
package main
import (
"github.com/dsbasko/go-cfg"
)
type Config struct {
Mode string `default:"prod" json:"mode" yaml:"mode" s-flag:"m" flag:"mode" env:"MODE" description:"mode of the application (dev|prod)"`
HTTP struct {
Host string `default:"localhost" json:"host" yaml:"host" s-flag:"h" flag:"http-host" env:"HTTP_HOST"`
Port int `default:"3000" json:"port" yaml:"port" s-flag:"p" flag:"http-port" env:"HTTP_PORT"`
ReadTimeout int `json:"read_timeout" yaml:"read-timeout" flag:"http-read-timeout" env:"HTTP_READ_TIMEOUT"`
WriteTimeout int `json:"write_timeout" yaml:"write-timeout" flag:"http-write-timeout" env:"HTTP_WRITE_TIMEOUT"`
} `json:"http" yaml:"http"`
}
func main() {
cfg := Config{}
gocfg.MustReadFile("configs/config.yaml", &cfg)
gocfg.MustReadEnv(&cfg)
gocfg.MustReadFlag(&cfg)
}
Note that you can configure the priority of the configuration. For example, you can first read YAML configs, then environment variables, and finally flags, or vice versa.
Run a project with flags: go run ./cmd/main.go -s="some short flag" --flat=f1 --nested n1
type config struct {
WithShort string `s-flag:"s" flag:"with-short" description:"With short flag"`
Flat string `flag:"flat" description:"Flat flag"`
Parent struct {
Nested string `flag:"nested" description:"Nested flag"`
}
}
func main() {
var cfg config
if err := gocfg.ReadFlag(&cfg); err != nil {
log.Panicf("failed to read flag: %v", err)
}
// or: gocfg.MustReadFlag(&cfg)
log.Printf("WithShort: %v\n", cfg.WithShort)
log.Printf("Flat: %v\n", cfg.Flat)
log.Printf("Nested: %v\n", cfg.Parent.Nested)
}
// WithShort: some short flag
// Flat: f1
// Nested: n1
Struct tags are available for working with flags:
default
default value;flag
the name of the flag;s-flag
short name of the flask (1 symbol);description
description of the flag that is displayed when running the--help
command.
The env
structure tag is used for environment variables.
Run a project with environment variables: FLAT=f1 NESTED=n1 go run ./cmd/main.go
type config struct {
Flat string `env:"FLAT"`
Parent struct {
Nested string `env:"NESTED"`
}
}
func main() {
var cfg config
if err := gocfg.ReadEnv(&cfg); err != nil {
log.Panicf("failed to read env: %v", err)
}
// or: gocfg.MustReadEnv(&cfg)
log.Printf("Flat: %v\n", cfg.Flat)
log.Printf("Nested: %v\n", cfg.Parent.Nested)
}
// Flat: f1
// Nested: n1
Struct tags are available for working with environment variables:
default
default value;env
the name of the environment variable.
Run a project with environment variables: go run ./cmd/main.go
type config struct {
Flat string `yaml:"flat"`
Parent struct {
Nested string `yaml:"nested"`
}
}
func main() {
var cfg config
if err := gocfg.ReadFile(path.Join("cmd", "config.yaml"), &cfg); err != nil {
log.Panicf("failed to read config.yaml file: %v", err)
}
// or: gocfg.MustReadFile(path.Join("cmd", "config.yaml"), &cfg)
log.Printf("Flat: %v\n", cfg.Flat)
log.Printf("Nested: %v\n", cfg.Parent.Nested)
}
// Flat: f1
// Nested: n1
Structure of the yaml
file:
flat: f1
foo:
nested: n1
Struct tags are available for working with environment variables:
default
default value;env
for files of the format.env
yaml
for files of the format.yaml
or.yml
toml
for files of the format.toml
json
for files of the format.json
If you enjoyed this project, I would appreciate it if you could give it a star! If you notice any problems or have any suggestions for improvement, please feel free to create a new issue. Your feedback means a lot to me!