Skip to content

os/gcfg: 新增支持标准配置优先级的获取方法 #4650

@lingcoder

Description

@lingcoder

背景

12-Factor App 推荐的配置优先级(从高到低):

命令行参数 > 环境变量 > 配置文件 > 默认值

这也是 Spring Boot、Viper 等主流框架采用的方式。高优先级的配置源可以覆盖低优先级的值,便于运维在部署时通过环境变量或命令行参数覆盖配置,而无需修改配置文件。

现状问题

当前 gcfg 提供的方法:

方法 优先级
Get 仅配置文件
GetWithEnv 配置文件 > 环境变量
GetWithCmd 配置文件 > 命令行

现有方法的优先级是配置文件优先,环境变量和命令行仅作为 fallback。这与 12-Factor App 的推荐相反,无法满足"通过环境变量/命令行覆盖配置文件"的常见需求。

此外,GetWithEnv / GetWithCmd 的命名容易造成误解,让用户误以为与 Spring Boot 类似——只是多了一个数据源,而没有意识到优先级是相反的。

建议方案

新增方法,采用标准优先级:

命令行参数 > 环境变量 > 配置文件 > 默认值

API 设计

// 按标准优先级获取配置值
// 优先级:命令行参数 > 环境变量 > 配置文件 > 默认值
func (c *Config) GetEffective(ctx context.Context, pattern string, def ...interface{}) (*gvar.Var, error)

// Must 版本
func (c *Config) MustGetEffective(ctx context.Context, pattern string, def ...interface{}) *gvar.Var

使用示例

// 配置文件 config.yaml:
//   server:
//     port: 8080

// 启动命令: ./app --server.port=9090
// 或环境变量: SERVER_PORT=9090 ./app

port := cfg.MustGetEffective(ctx, "server.port", 8000)
// 优先使用命令行参数 9090
// 若无命令行参数,使用环境变量 SERVER_PORT
// 若无环境变量,使用配置文件 8080
// 若无配置文件,使用默认值 8000

关于命名

暂定命名为 GetEffective,表示"经过优先级合并后实际生效的值"。"Effective" 在配置领域是常用术语,Kubernetes 中也有类似用法,如 effectiveAnnotationseffectivePodSecurityPolicy 等表示最终生效的配置。

命名仅供参考,可根据讨论调整。

兼容性

  • 保留现有 GetGetWithEnvGetWithCmd 方法,不做任何改动
  • 新方法推荐作为获取配置的首选方式
  • 在文档中说明各方法的优先级差异,引导用户根据场景选择

相关参考

Metadata

Metadata

Assignees

No one assigned

    Labels

    awesomeIt's awesome! We keep watching.discussWe need discuss to make decision.feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions