子网站建设的好处,网站建设198,网站qq在线代码,云盘网站如何做在实际开发中#xff0c;我们往往会给一个逻辑设计一套配置文件#xff0c;用于根据不同环境加载不同配置。 比如生产环境和测试环境数据库的地址不一样#xff0c;我们就需要在配置文件中设置不同的值。但是配置文件中又有一些相同值的配置项#xff0c;比如数据库的名称等…在实际开发中我们往往会给一个逻辑设计一套配置文件用于根据不同环境加载不同配置。 比如生产环境和测试环境数据库的地址不一样我们就需要在配置文件中设置不同的值。但是配置文件中又有一些相同值的配置项比如数据库的名称等。难道相同的配置要像下面这样写多次吗
version: 1
pro:write_pool:url: pro-write.comport: 11port: 5432user_name: write_pool_user_namepassword: write_pool_passworddbname: dbnamemax_idle_Conns: 1max_open_conns: 1conn_max_lifetime_seconds: 3user:username: unpassword: pwdread_pool:url: pro-read.comport: 5432user_name: read_pool_user_namepassword: read_pool_passworddbname: dbnamemax_idle_Conns: 1max_open_conns: 1conn_max_lifetime_seconds: 3user:username: unpassword: pwd
dev:write_pool:url: dev-write.comport: 11port: 5432user_name: write_pool_user_namepassword: write_pool_passworddbname: dbnamemax_idle_Conns: 1max_open_conns: 1conn_max_lifetime_seconds: 3user:username: unpassword: pwdread_pool:url: dev-read.comport: 5432user_name: read_pool_user_namepassword: read_pool_passworddbname: dbnamemax_idle_Conns: 1max_open_conns: 1conn_max_lifetime_seconds: 3user:username: unpassword: pwd一种简单的办法是我们设置一个默认项default用于填充相同的值然后在不同环境中填充不同的值。比如下例
# db.yaml
version: 1
pro:write_pool:url: pro-write.comport: 11read_pool:url: pro-read.com
pre:write_pool:url: pre-write.comread_pool:url: pre-read.com
test:write_pool:url: test-write.comread_pool:url: test-read.com
dev:write_pool:url: dev-write.comread_pool:url: dev-read.com
default:write_pool:port: 5432user_name: write_pool_user_namepassword: write_pool_passworddbname: dbnamemax_idle_Conns: 1max_open_conns: 1conn_max_lifetime_seconds: 3user:username: unpassword: pwdread_pool:port: 5432user_name: read_pool_user_namepassword: read_pool_passworddbname: dbnamemax_idle_Conns: 1max_open_conns: 1conn_max_lifetime_seconds: 3user:username: unpassword: pwd这样我们在取pro、pre、dev和test环境的配置时会让它们和default取合集从而变成一个完整的配置。
实现
具体实现如下
package configparserimport (fmtosreflectgopkg.in/yaml.v3
)type Config struct {Version string yaml:versionPro interface{} yaml:proPre interface{} yaml:preDev interface{} yaml:devTest interface{} yaml:testDefault interface{} yaml:default
}const (ErrorEnvNotfound env [%s] not foundKeyFieldTag yaml
)func LoadConfigFromFile(filePath string, env string) (string, error) {data, err : os.ReadFile(filePath)if err ! nil {return , err}return LoadConfigFromMemory(data, env)
}func LoadConfigFromMemory(configure []byte, env string) (string, error) {var config Configerr : yaml.Unmarshal(configure, config)if err ! nil {return , err}configReflectType : reflect.TypeOf(config)for i : 0; i configReflectType.NumField(); i {structTag : configReflectType.Field(i).Tag.Get(KeyFieldTag)if structTag env {envConfigReflect : reflect.ValueOf(config).Field(i).Interface()defauleConfigReflectType : config.Defaultif envConfigReflect nil defauleConfigReflectType nil {return , fmt.Errorf(ErrorEnvNotfound, env)}if envConfigReflect nil {defaultConf, err : yaml.Marshal(config.Default)if err ! nil {return , err}return string(defaultConf), nil}if defauleConfigReflectType nil {envConf, err : yaml.Marshal(reflect.ValueOf(config).Field(i).Interface())if err ! nil {return , err}return string(envConf), nil}merged : mergeMapStringInterface(reflect.ValueOf(config).Field(i).Interface().(map[string]interface{}), config.Default.(map[string]interface{}))mergedConf, err : yaml.Marshal(merged)if err ! nil {return , err}return string(mergedConf), nil}}return , fmt.Errorf(ErrorEnvNotfound, env)
}func mergeMapStringInterface(cover map[string]interface{}, base map[string]interface{}) map[string]interface{} {for k, v : range cover {switch v.(type) {case map[string]interface{}:if base[k] nil {base[k] v} else {mergeMapStringInterface(v.(map[string]interface{}), base[k].(map[string]interface{}))}default:base[k] v}}return base
}调用例子
package mainimport (fmtconfigparser gconfospathgopkg.in/yaml.v3
)type PostgresSqlConnConfigs struct {WritePool PostgresSqlConnPoolConf yaml:write_poolReadPool PostgresSqlConnPoolConf yaml:read_pool
}type PostgresSqlConnPoolConf struct {Url *string yaml:urlPort *string yaml:portUserName *string yaml:user_namePassword *string yaml:passwordDbName *string yaml:dbnameMaxIdleConn *int yaml:max_idle_ConnsMaxOpenConn *int yaml:max_open_connsConnMaxLifetimeSeconds *int64 yaml:conn_max_lifetime_secondsUserA *User yaml:user
}type User struct {Username *string yaml:usernamePassword *string yaml:password
}func main() {runPath, _ : os.Getwd()confPath : path.Join(runPath, conf/db.yaml)env : []string{dev, test, pre, pro}for _, v : range env {var conf ExampleConfigcurConfig, err : configparser.LoadConfigFromFile(confPath, v)if err ! nil {fmt.Printf(load config file failed, err: %v, err)}err yaml.Unmarshal([]byte(curConfig), conf)if err ! nil {fmt.Printf(unmarshal config file failed, err: %v, err)}fmt.Printf(%s\nconfig: %v\n, v, conf)}
}