Documentation
¶
Overview ¶
Package wonsz binds a plain Go configuration struct to configuration files, environment variables and cobra command-line flags at once — the best of viper and cobra combined, without writing any binding boilerplate.
Define a struct, call New (or the convenience wrapper BindConfig) and every field is readable from a config file (snake_case keys), environment variables (SCREAMING_SNAKE_CASE) and command-line flags (kebab-case), with the usual precedence: flags > env > config file > defaults.
type Config struct {
SnakeName string `default:"nope-rope" usage:"the snake's name"`
}
var cfg Config
w, err := wonsz.New(&cfg, rootCmd, wonsz.ConfigOpts{EnvPrefix: "APP"})
Field behavior can be tuned with optional struct tags: mapstructure (custom key), default, usage, shortcut, wonsz:"flag-ignore" (no flag) and wonsz:"-" (excluded entirely). See ConfigOpts for file lookup, custom viper instances and config hot-reload via WatchConfig.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BindConfig ¶
func BindConfig[T any](config *T, rootCmd *cobra.Command, options ConfigOpts) error
BindConfig binds the configuration structure to a config file, environment variables and cobra command flags. It is a convenience wrapper around New for callers that do not need the returned instance. You can pass nil to rootCmd if you don't want to bind cobra command flags with config.
Example ¶
_ = os.Setenv("EXAMPLE_FIELD", "this is my example config field")
var myConfig struct {
ExampleField string
}
err := BindConfig(&myConfig, nil, ConfigOpts{})
if err != nil {
panic(err)
}
fmt.Println(myConfig.ExampleField)
Output: this is my example config field
Types ¶
type ConfigOpts ¶
type ConfigOpts struct {
// Environment variables prefix.
// E.g., if your prefix is "wonsz", the env registry will look for env variables that start with "WONSZ_".
EnvPrefix string
// Paths to search for the config file in.
ConfigPaths []string
// Type of the configuration file, e.g. "json".
// Wonsz uses Viper for loading the configuration file,
// so you can use any type of configuration file that Viper supports.
ConfigType string
// Name for the config file. Does not include extension.
// If no configuration name is specified, Wonsz will not throw an error if the config file is not found.
ConfigName string
// Pass own viper instance. Default is a global viper instance.
Viper *globalViper.Viper
// If true, Wonsz will not return an error if a config field cannot be bound to a flag
// or the resulting flag cannot be bound to viper. Such fields are silently skipped.
IgnoreFlagBindErrors bool
// If true, Wonsz watches the config file and re-unmarshals the config struct
// when the file changes. Note that the struct is updated from a background
// goroutine, so guard access to it if your application reads it concurrently.
WatchConfig bool
// Called after each WatchConfig reload with the re-unmarshal result.
// Runs on the watcher goroutine, right after the config struct is updated,
// so it is a safe synchronization point for reacting to config changes.
OnConfigChange func(err error)
}
ConfigOpts provide additional options to configure Wonsz.
type Tag ¶
type Tag struct {
// contains filtered or unexported fields
}
Tag contains the name and value of a structure field tag.
func GetTagsForField ¶
func GetTagsForField(field reflect.StructField) []Tag
GetTagsForField extracts field tag names and values from a specified structure.
type Wonsz ¶ added in v0.3.0
type Wonsz[T any] struct { // contains filtered or unexported fields }
Wonsz binds a single configuration struct of type T to a config file, environment variables and cobra command flags. Create instances with New; each instance keeps its own options and viper, so multiple configs can coexist.
func New ¶ added in v0.3.0
New binds the configuration structure to a config file, environment variables and cobra command flags, and returns an independent Wonsz instance. The config parameter must be a non-nil pointer to a struct. You can pass nil to rootCmd if you don't want to bind cobra command flags with config.
Example ¶
package main
import (
"fmt"
"os"
"github.com/Mrucznik/wonsz"
"github.com/spf13/viper"
)
func main() {
_ = os.Setenv("SNAKE_NAME", "danger noodle")
defer func() { _ = os.Unsetenv("SNAKE_NAME") }()
type Config struct {
SnakeName string
SnakeLength int `default:"5"`
}
var cfg Config
w, err := wonsz.New(&cfg, nil, wonsz.ConfigOpts{Viper: viper.New()})
if err != nil {
panic(err)
}
// Get returns the typed pointer, no type assertion needed.
fmt.Println(w.Get().SnakeName, w.Get().SnakeLength)
}
Output: danger noodle 5
Example (Tags) ¶
package main
import (
"fmt"
"os"
"github.com/Mrucznik/wonsz"
"github.com/spf13/viper"
)
func main() {
_ = os.Setenv("CUSTOM_NAME", "hazard spaghetti")
defer func() { _ = os.Unsetenv("CUSTOM_NAME") }()
type Config struct {
Renamed string `mapstructure:"custom_name"`
Excluded string `wonsz:"-"`
}
var cfg Config
if err := wonsz.BindConfig(&cfg, nil, wonsz.ConfigOpts{Viper: viper.New()}); err != nil {
panic(err)
}
fmt.Printf("%q %q\n", cfg.Renamed, cfg.Excluded)
}
Output: "hazard spaghetti" ""
func (*Wonsz[T]) Get ¶ added in v0.3.0
func (w *Wonsz[T]) Get() *T
Get returns the config struct instance passed to New.
func (*Wonsz[T]) Viper ¶ added in v0.3.0
func (w *Wonsz[T]) Viper() *globalViper.Viper
Viper returns the viper instance used by this Wonsz instance.
