Áttekintés
Az envconf önálló Go modul (github.com/gp-system/envconf): típusos konfiguráció, környezeti változókból egy Go structba betöltve, egyszer, a folyamat indulásakor, opcionális .env fájllal a helyi fejlesztéshez. Két függősége van, a caarlos0/env (a struct-tag parser) és a joho/godotenv (.env fájl betöltés), és semmilyen gp-system-specifikus tudása nincs: bármilyen Go programban ugyanúgy működik. A gpsystem kit az egyetlen betöltési lépésként használja, amit minden generált projekt lefuttat a main()-ben; lásd a Konfiguráció oldalt, hogy egy projekt hogyan komponál vele tucatnyi modul beállítását egyetlen structba.
Telepítés
go get github.com/gp-system/envconf@v0.1.0 # a kit is ezt a taget használja
go get github.com/gp-system/envconf@latest
Go 1.25+. Függőség-lábnyom: caarlos0/env/v11 és joho/godotenv, semmi más.
Load, MustLoad, LoadPrefixed
func Load[T any]() (T, error)
func MustLoad[T any]() T
func LoadPrefixed[T any](prefix string) (T, error)
A Load a környezeti változókat egy új T-be parseolja, az env:"..." struct-tageket követve, és visszaadja a feltöltött értéket vagy egy hibát (hiányzó required változó, vagy egy érték, ami nem parseolható a mező típusára). A MustLoad ugyanaz, de hiba visszaadása helyett panicol: ez az a forma, amit valójában a main() elején akarsz, ahol egy konfigurációs hibával nincs mit értelmesen kezdeni, csak gyorsan és hangosan elbukni.
type Config struct {
ListenAddr string `env:"LISTEN_ADDR" envDefault:":3000"`
DBHost string `env:"DB_HOST,required"`
Timeout time.Duration `env:"TIMEOUT" envDefault:"5s"`
}
cfg := envconf.MustLoad[Config]()
A LoadPrefixed a Load, de minden mező környezeti változója extra prefixet kap; akkor hasznos, amikor ugyanazt a konfig-formát több, mint egyszer be kell tölteni, más néven (lásd a Receptek oldalon egy két-Valkey-kapcsolat példát):
primary, err := envconf.LoadPrefixed[ValkeyConfig]("PRIMARY_") // PRIMARY_ADDR, PRIMARY_PASSWORD, ...
replica, err := envconf.LoadPrefixed[ValkeyConfig]("REPLICA_") // REPLICA_ADDR, REPLICA_PASSWORD, ...
Tagek és defaultok
Maga a parseolás a caarlos0/env-é: az envconf a .env-betöltési lépést teszi elé, semmi mást. A tagek, amik napi szinten számítanak:
| Tag | Jelentés |
|---|---|
env:"NAME" | az olvasandó környezeti változó |
env:"NAME,required" | elbuktatja a Load/MustLoad-ot, ha a változó nincs beállítva |
envDefault:"value" | akkor használja, ha a változó nincs beállítva (és nem required) |
envPrefix:"DB_" | egy beágyazott struct mezőn minden saját tagjét prefixeli |
envSeparator:"," | slice mezőknél az értékek közti elválasztó |
A mezőtípusok a Go szokásos parseolását követik: string, int, bool, time.Duration, []string, és bármi, ami implementálja az encoding.TextUnmarshaler-t. Egy required mező, default nélkül és beállított érték nélkül, pontosan az a hiba, amit a Load-nak el kell kapnia, mielőtt a folyamat elindul, nem az első kérésen, ami hozzáér.
.env betöltés
Parseolás előtt a Load/MustLoad/LoadPrefixed betölt egy .env fájlt a munkakönyvtárból godotenv-en keresztül, best-effort alapon: egy hiányzó .env fájl nem hiba. Ami lényeges: a godotenv sosem ír felül egy már beállított környezeti változót, tehát a .env csak a hiányokat tölti ki, sosem árnyékolja be azt az értéket, amit a valódi környezet már megadott. Ez az egyetlen szabály teszi lehetővé, hogy ugyanaz a Config struct mindenhol helyesen viselkedjen:
- Helyi fejlesztés, semmi exportálva a shellben: minden érték a
.env-ből jön. - Docker-compose dev stack: ugyanaz a
.envfájl, a szolgáltatás-hostnevek a compose hálózatára oldódnak fel, nem alocalhost-ra. - Staging/production: a valódi környezet (systemd, egy Kubernetes ConfigMap/Secret) közvetlenül állítja be a változókat; a
.envjellemzően hiányzik, és ha egy elfeledett mégis ott lenne, a már beállított változók akkor is nyernek.
Ez a .env-et tisztán fejlesztői kényelemmé teszi: semmi nem változik abban, hogyan töltődik be a konfig a környezetek közt, csak abban, hogy mi adja az értékeket.
Önálló példa
package main
import (
"fmt"
"time"
"github.com/gp-system/envconf"
)
type Config struct {
ListenAddr string `env:"LISTEN_ADDR" envDefault:":3000"`
APIKey string `env:"API_KEY,required"`
Timeout time.Duration `env:"TIMEOUT" envDefault:"5s"`
}
func main() {
cfg := envconf.MustLoad[Config]()
fmt.Printf("listening on %s, timeout %s\n", cfg.ListenAddr, cfg.Timeout)
}
API_KEY=dev-secret
TIMEOUT=10s
Futtasd shell-exportok nélkül (az API_KEY és a TIMEOUT a .env-ből jön, a LISTEN_ADDR a defaultjára esik vissza), vagy állítsd be az API_KEY-t a valódi környezetben és töröld a .env-et teljesen: a program azonosan viselkedik mindkét esetben.
Kapcsolódó oldalak
- envconf: Receptek: root config összeállítása modul-configokból, prefixelt multi-instance betöltések, tesztelés
t.Setenv-vel. - Konfiguráció: mit komponál egy generált gpsystem projekt az
envconf-fal, és a modulok közti prefix-konvenciók. - Konfigurációs referencia: minden modul minden env-változója, defaultokkal.