feat: load explicit configuration references and remove implicit env overlays
This commit is contained in:
@@ -10,11 +10,13 @@ DEMO_CLIENT_TIMEOUT=500ms DEMO_MAX_ITEMS=0 go run ./examples/configuration
|
||||
DEMO_MAX_ITEMS=wrong go run ./examples/configuration
|
||||
```
|
||||
|
||||
前三次都输出 `timeout=2s maxItems=100 allowed=[json xml]`。环境覆盖允许显式零值。
|
||||
前三次都输出 `timeout=2s maxItems=100 allowed=[json xml]`。文件显式引用允许零值。
|
||||
最后一条输出定位 `maxItems` / `DEMO_MAX_ITEMS` 的安全错误,不打印输入原值。
|
||||
也可 `-config /path/to/app.yaml` 读取自己的文件。示例没有建立网络连接。
|
||||
|
||||
`Config` 定义字段,`envDefault` 定义缺省值,`Validate` 用 `config.Invalid` 返回字段与公开原因。
|
||||
`Config` 定义字段,`Default()` 定义初始值,`Validate` 用 `config.Invalid` 返回字段与公开原因。
|
||||
文件中的 `${NAME}` 必填,`${NAME:-value}` 支持空/未设置的备用值,`$${NAME}` 保留字面量;字符串不裁剪,也不二次展开。没有出现在文件引用中的变量不会被读取。
|
||||
|
||||
`newLoader` 额外注册 `.custom`(演示复用 JSON decoder);同一个 `load` 可读取所有格式。
|
||||
JSON/YAML/XML 直接可用,无需注册。新增格式只修改解析器注册,不改业务结构或校验。
|
||||
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
{
|
||||
"client": {"endpoint": "https://example.com", "timeout": "2s"},
|
||||
"maxItems": 100,
|
||||
"allowed": ["json", "xml"]
|
||||
}
|
||||
{"client":{"endpoint":"https://${DEMO_HOST:-example.com}","timeout":"${DEMO_CLIENT_TIMEOUT:-2s}","token":"${DEMO_CLIENT_TOKEN:-}"},"maxItems":"${DEMO_MAX_ITEMS:-100}","allowed":["json","xml"]}
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
<config>
|
||||
<client>
|
||||
<endpoint>https://example.com</endpoint>
|
||||
<timeout>2s</timeout>
|
||||
</client>
|
||||
<maxItems>100</maxItems>
|
||||
<allowed type="array"><item>json</item><item>xml</item></allowed>
|
||||
</config>
|
||||
<config><client><endpoint>https://${DEMO_HOST:-example.com}</endpoint><timeout>${DEMO_CLIENT_TIMEOUT:-2s}</timeout><token>${DEMO_CLIENT_TOKEN:-}</token></client><maxItems>${DEMO_MAX_ITEMS:-100}</maxItems><allowed type="array"><item>json</item><item>xml</item></allowed></config>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
client:
|
||||
endpoint: https://example.com
|
||||
timeout: 2s
|
||||
maxItems: 100
|
||||
endpoint: "https://${DEMO_HOST:-example.com}"
|
||||
timeout: "${DEMO_CLIENT_TIMEOUT:-2s}"
|
||||
token: "${DEMO_CLIENT_TOKEN:-}"
|
||||
maxItems: "${DEMO_MAX_ITEMS:-100}"
|
||||
allowed: [json, xml]
|
||||
|
||||
@@ -17,16 +17,18 @@ var examples embed.FS
|
||||
|
||||
type ClientConfig struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
Timeout time.Duration `json:"timeout" envDefault:"3s"`
|
||||
// This field is deliberately unavailable to configuration files.
|
||||
Token string `json:"-" env:"DEMO_CLIENT_TOKEN,secret"`
|
||||
Timeout time.Duration `json:"timeout"`
|
||||
// The file chooses a fixed value or an explicit environment reference.
|
||||
Token string `json:"token"`
|
||||
}
|
||||
type Config struct {
|
||||
Client ClientConfig `json:"client"`
|
||||
MaxItems int `json:"maxItems" envDefault:"20"`
|
||||
MaxItems int `json:"maxItems"`
|
||||
Allowed []string `json:"allowed"`
|
||||
}
|
||||
|
||||
func Default() Config { return Config{Client: ClientConfig{Timeout: 3 * time.Second}, MaxItems: 20} }
|
||||
|
||||
func (c Config) Validate() error {
|
||||
if c.Client.Timeout <= 0 {
|
||||
return config.Invalid("client.timeout", "must be positive")
|
||||
@@ -48,7 +50,7 @@ func load(path string) (Config, error) {
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
return config.LoadProject(path, Config{}, config.EnvOptions{Prefix: "DEMO_", Empty: "reject"}, loader)
|
||||
return config.LoadProject(path, Default(), loader)
|
||||
}
|
||||
func run() error {
|
||||
path := flag.String("config", "", "external configuration file")
|
||||
|
||||
Reference in New Issue
Block a user