Defaults
Seed empty fields from their default tag without ever overriding real input.
A field's default: tag value is applied when the field is left empty. A default never overrides a value that is already present, so a near-empty input map still yields a fully populated, runnable config while any value you did provide stays exactly as given.
type ServerConfig struct {
Host string `json:"host" default:"0.0.0.0"`
Port int `json:"port" default:"8080"`
LogLevel string `json:"log_level" default:"info"`
Database Database `json:"database"`
}
type Database struct {
DSN string `json:"dsn" default:"" rules:"required"`
}
cfg := &ServerConfig{}
manager := structs.New(cfg)
// only the DSN is provided, addressed by its dotted path.
inputs := map[string]any{
"database.dsn": "postgres://localhost/app",
}
_ = manager.Set(inputs)
// cfg.Host == "0.0.0.0", cfg.Port == 8080, cfg.LogLevel == "info"
// cfg.Database.DSN == "postgres://localhost/app"Defaults are applied per field as Set walks the struct, so nested fields default independently of their parent. A field with no default: tag and no input is left at its Go zero value.
Tip
Defaults compose with validation. Because the default is applied before a rule is checked, a field with default:"info" and rules:"required" passes required on the strength of its default, and a field with default:"info" rules:"oneof:debug,info,warn,error" is validated against its default when no input arrives. See Validation.