配置管理
配置管理
Viper 是 Go 配置管理库,支持默认值、配置文件、环境变量、命令行参数和远程配置等来源。
go get github.com/spf13/viper
读取配置
建议创建独立实例,避免全局状态影响测试和多个配置模块。
type Config struct {
Server struct {
Port int `mapstructure:"port"`
} `mapstructure:"server"`
DatabaseURL string `mapstructure:"database_url"`
}
v := viper.New()
v.SetConfigName("config")
v.SetConfigType("yaml")
v.AddConfigPath(".")
v.SetDefault("server.port", 8080)
v.SetEnvPrefix("APP")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.AutomaticEnv()
v.BindEnv("database_url")
if err := v.ReadInConfig(); err != nil {
var notFound viper.FileLookupError
if !errors.As(err, ¬Found) {
return Config{}, err
}
}
var config Config
if err := v.Unmarshal(&config); err != nil {
return Config{}, err
}
对应的 config.yaml:
server:
port: 8080
database_url: postgres://localhost/app
环境变量 APP_DATABASE_URL 会覆盖配置文件中的 database_url。Viper 的优先级从高到低为:显式 Set、命令行参数、环境变量、配置文件、远程配置和默认值。
绑定命令行参数
Viper 可以直接绑定 Cobra 使用的 pflag:
flags.Int("port", 8080, "HTTP server port")
v.BindPFlag("server.port", flags.Lookup("port"))
绑定操作不会立即读取参数值,调用 Get 或 Unmarshal 时才会解析最终配置。
实践建议
- 读取完成后映射到结构体,再把
Config注入业务组件,不要让业务代码到处调用viper.Get。 - 显式绑定需要覆盖的环境变量,避免环境变量存在但未进入
Unmarshal结果。 - 密码和 Token 不应提交到配置文件,应通过环境变量或密钥管理系统注入。
- 动态监听配置前先确认组件是否支持并发更新;数据库连接等资源通常不能只修改字段就完成热更新。
- Viper 不会深度合并复杂配置,某个嵌套值被覆盖时,整个值可能被替换。