English | 简体中文
genv decodes environment variables into Go structs with tags.
It is extracted from a production project (lovetalk.ai) and keeps compatible tags while improving edge-case handling for reusable libraries.
go get github.com/aak1247/genv@latestpackage main
import (
"fmt"
"time"
"github.com/aak1247/genv"
)
type Config struct {
Server struct {
Host string `default:"0.0.0.0"`
Port int `default:"8080"`
}
OpenAI struct {
Keys []string `env:"OPENAI_KEYS" slice_sep:"," require:"true"`
Timeout time.Duration `env:"OPENAI_TIMEOUT" default:"10s"`
UseProxy bool `env:"OPENAI_USE_PROXY" default:"false"`
ProxyURL string `env:"OPENAI_PROXY"`
RetryTimes int `env:"OPENAI_RETRY_TIMES" default:"3"`
}
}
func main() {
var cfg Config
if err := genv.Fill(&cfg); err != nil {
panic(err)
}
fmt.Println(cfg.Server.Host, cfg.Server.Port)
}You can register and retrieve config as a singleton by type:
type Config struct {
Server struct {
Host string `default:"127.0.0.1"`
}
}
// Optional eager init (first registration wins for options).
if err := genv.Register[Config](genv.WithIgnorePrefix(true)); err != nil {
panic(err)
}
cfg, err := genv.Get[Config]()
if err != nil {
panic(err)
}
// Or fail fast during startup:
genv.MustRegister[Config](genv.WithIgnorePrefix(true))
_ = cfgenv: explicit env key. Useenv:"-"to skip this field.default: fallback value when env key is absent.require: whether env key must exist (true/false).sep: custom separator while generating nested names.slice_sep: separator for slices, default is;.
If env tag is not set, key name is generated by:
- Root prefix: upper-cased root struct name (unless
WithIgnorePrefix(true)/IgnorePrefix()). - Nested field key:
PARENT + "_" + UPPER(FIELD_NAME)(or customsep).
Example:
- Root type:
Config - Field:
Database.Host - Generated key:
CONFIG_DATABASE_HOST
genv.Fill(&cfg): use global parser.genv.MustFill(&cfg): panic on error.genv.Parse(&cfg, genv.WithIgnorePrefix(true)): use one-off parser options.genv.IgnorePrefix(): mutate global parser to ignore root prefix.genv.Register[T](opts...): eager init singleton forT.genv.MustRegister[T](opts...): fail-fast version of register.genv.Get[T](): lazy/eager singleton access forT.
- Scalars:
string,bool, allint*, alluint*,float32,float64 time.Duration- Slices of all supported scalar types
- Custom types implementing
encoding.TextUnmarshaler