如何将参数配置化
在实习过程中,遇到一个很常见的需求,那就是将一些变量值可以通过配置导入
比如下面这个原本写死的变量:
const (
ListeningAddress = "0.0.0.0:18888"
RealPoolAddress = "127.0.0.1:3333"
)
实现思路
1.肯定是先写一个结构体来存这个配置值
type Config struct {
ListeningAddress string `yaml:"listening_address" json:"listening_address"`
RealPoolAddress string `yaml:"real_pool_address" json:"real_pool_address"`
}
那么我原本既然是写死的一个值,那肯定代表我默认情况下是这样的值,那必然下一步思路是设置一个默认值,于是:
2.配置一个默认值
func DefaultConfig() *Config{
return &Config{
ListeningAddress: "0.0.0.0:18888",
RealPoolAddress: "127.0.0.1:3333",
}
}
有了默认值,下一步必然就是,通过配置文件加载,于是:
3.加载配置
下面就是实现LoadConfig
:
按照优先级:命令行>配置文件>默认值。所以:
func LoadConfig()(*Config,error){
// 1. 默认配置
config := DefualtConfig()
// 2. 加载配置文件
...
// 3. 加载命令行
...
}
所以下面依次简单实现loadFromFile
和loadFromFlags
方法,对应配置文件
和命令行
func loadFromFile(config *Config, filename string) err{
if _,err := os.state(filename); os.IsNotExist(err){return err}
// 解析
data,err:= os.ReadFile(filename)
if err!=nil{return err}
ext:= strings.ToLower(filepath.Ext(filename))
switch ext{
case ".yaml",".yml" : return yaml.Unmarshal(data,config)
default: return yaml.Unmarshal(data,config)
}
}
func loadFromFlags(config *Config) {
listenAddr := flag.String("listen",config.ListeningAddress,"listening address")
poolAddr := flag.String("pool",config.RealPoolAddress,"real pool address")
// 解析命令行
flag.Parse()
// 更新配置
if *listeningAddr != config.ListeningAddress {
config.ListeningAddress = *listeningAddr
}
if *poolAddr != config.RealPoolAddress {
config.RealPoolAddress = *poolAddr
}
}
4.方便使用的一些工具方法
先声明一个配置接口:
// Config 配置接口,用于获取地址参数
type Config interface {
GetListeningAddress() string
GetRealPoolAddress() string
}
为Config结构体实现该接口:
// GetListeningAddress 获取监听地址
func (c *Config) GetListeningAddress() string {
return c.ListeningAddress
}
// GetRealPoolAddress 获取真实矿池地址
func (c *Config) GetRealPoolAddress() string {
return c.RealPoolAddress
}
// Validate 验证配置的有效性
func (c *Config) Validate() error {
if c.ListeningAddress == "" {
return &ConfigError{Field: "listening_address", Message: "监听地址不能为空"}
}
if c.RealPoolAddress == "" {
return &ConfigError{Field: "real_pool_address", Message: "真实矿池地址不能为空"}
}
return nil
}
// ConfigError 配置错误类型
type ConfigError struct {
Field string
Message string
}
func (e *ConfigError) Error() string {
return e.Field + ": " + e.Message
}
总结
➡️ 定义配置结构体
➡️ 设定默认值 DefaultConfig()
➡️ 加载配置文件
➡️ 支持命令行/环境变量覆盖
➡️ 提供统一访问接口,校验配置有效性等 (如 Config 接口 ,Validate ,ConfigError)