Configuration management is an essential part of any application development. In Go, the standard flag
package provides a convenient way to work with command-line flags. However, in practice, there is often a need to support not only CLI arguments but also other sources such as YAML files, environment variables, and more.
zerocfg is a lightweight library that preserves the simplicity and familiar interface of the flag
package while adding support for YAML, environment variables (env), and custom configuration sources.
✅ Key Features
- 🛠️ Intuitive API, similar to
flag
- 🧼 Minimizes boilerplate code
- 🔍 Detects unknown keys in the configuration
- 📚 Supports multiple sources: CLI, YAML, ENV, and others
- 🔐 Hides sensitive data (e.g., passwords) when printing configurations
- 🧩 Extensible: supports custom types and providers
🚀 Usage Example
package main
import (
"fmt"
zfg "github.com/chaindead/zerocfg"
"github.com/chaindead/zerocfg/env"
)
var (
databaseHost = *zfg.Str("db.host", "postgres", "database host")
databasePort = *zfg.Uint("db.port", 5678, "database port")
databaseUserName = *zfg.Str("db.username", "postgres", "database user name")
databaseUserPassword = *zfg.Str("db.password", "", "database user password", zfg.Required(), zfg.Secret())
databaseName = *zfg.Str("db.name", "app", "database name")
)
func main() {
err := zfg.Parse(env.New())
if err != nil {
panic(err)
}
fmt.Println(zfg.Show())
databaseDSN := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", databaseUserName, databaseUserPassword, databaseHost, databasePort, databaseName)
_ = databaseDSN
}
🔁 Configuration Source Priority
Priorities determine which values will be used if they are defined in multiple sources:
- Command-line flags (highest priority)
- Additional providers (in the order they are listed)
- Default values (lowest priority)
This mechanism allows flexible parameter configuration and overrides depending on the application’s runtime context.
📦 Supported Sources
- CLI (command-line flags)
- ENV (environment variables)
- YAML (configuration files)
CLI Example
go run main.go --db.host localhost --db.port 6432 --db.username admin --db.password pass --db.name postgres
ENV Example
DB_HOST=localhost DB_PORT=6432 DB_USERNAME=admin DB_PASSWORD=pass DB_NAME=postgres go run main.go
YAML Example
To use a YAML file, you need to slightly modify the source code:
package main
import (
"fmt"
zfg "github.com/chaindead/zerocfg"
"github.com/chaindead/zerocfg/env"
"github.com/chaindead/zerocfg/yaml"
)
var (
path = zfg.Str("config.path", "", "configuration file path", zfg.Alias("c"))
databaseHost = *zfg.Str("db.host", "postgres", "database host")
databasePort = *zfg.Uint("db.port", 5678, "database port")
databaseUserName = *zfg.Str("db.username", "postgres", "database user name")
databaseUserPassword = *zfg.Str("db.password", "", "database user password", zfg.Required(), zfg.Secret())
databaseName = *zfg.Str("db.name", "app", "database name")
)
func main() {
err := zfg.Parse(env.New(), yaml.New(path))
if err != nil {
panic(err)
}
fmt.Println(zfg.Show())
databaseDSN := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", databaseUserName, databaseUserPassword, databaseHost, databasePort, databaseName)
_ = databaseDSN
}
Create a config.yml
file with the following content:
db:
host: "postgres"
port: 5432
username: "postgres"
password: "postgres_pass"
name: "app"
Then run the app like this:
go run main.go -c config.yml
📋 Additional Options
- Fields marked with
zfg.Secret()
are hidden when printed viazfg.Show()
— useful for passwords and tokens. - Fields with
zfg.Required()
are considered mandatory — if they are not provided in any source, an error will be returned.
Example:
databaseUserPassword = *zfg.Str("db.password", "", "database user password", zfg.Required(), zfg.Secret())
🧱 Extensibility
The library supports custom data types and custom configuration providers, making it flexible and adaptable to any project needs.
📝 Conclusion
The zerocfg library offers a simple yet powerful way to manage configuration in Go applications. While preserving the familiar interface of the standard flag
package, it extends its capabilities with support for YAML files, environment variables, and custom configuration sources. Its intuitive API, minimal boilerplate, unknown key detection, and sensitive data masking make it an excellent choice for modern applications.
If you're looking for a lightweight and extensible configuration management library for Go — zerocfg is a great fit for your project.
📌 What do you think?
Have you tried zerocfg or other configuration management tools in Go yet?
What libraries or approaches do you use in your projects to handle application settings?
👇 Leave a comment below — I’d love to hear your experience!
👍 Don’t forget to like and share if you found this helpful — so more people can benefit from it too!
📣 Follow me and read my content on other platforms:
Check out this and other articles on my pages:
🔗 LinkedIn
📚 Medium
📘 Facebook
✈️ Telegram
🐦 X
Oh, almost forgot — my personal website.
🔔 Follow me not to miss new articles and guides on hot topics!