I am working on a utility method lets say GetConfig(), which reads the config struct and return it to the caller. GetConfig() does not know what config it is going to read, but the caller knows the struct what it is going to receive.
In this regard, I have written a below utility program:
=========== yaml file data ==========
apiRouting:
enableThrottling: true
formFactor: 4
leasing:
periodInSecs: 10
preemptionEnable: false
=========== yaml file data ==========
func GetConfig() (interface{}, error) {
fmt.Println("reading generic service config")
viper.SetConfigName("service_config")
viper.AddConfigPath("config/default")
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
var appConfig interface{}
if err := viper.Unmarshal(&appConfig); err != nil {
return nil, err
}
return appConfig, nil
}
Caller uses GetConfig() like this: (I have tried 2 options, nothing is working)
type ApiRouting struct {
EnableThrottling bool `json:"enableThrottling"`
FormFactor int32 `json:"formFactor"`
}
type Leasing struct {
PeriodInSecs int32 `json:"periodInSecs"`
PreemptionEnable bool `json:"preemptionEnable"`
}
type ServiceConfig struct {
ApiRouting ApiRouting `json:"apiRouting"`
Leasing Leasing `json:"leasing"`
}
// code snipped [option 1]
tmpinterface := GetConfig()
myconfig, ok := tmpinterface.(ServiceConfig)
if !ok {
log.Fatal()
} else {
println(myconfig)
}
// code snipped [option 2]
tmpinterface := GetConfig()
// Convert map to json string
jsonStr, err := json.Marshal(tmpinterface)
if err != nil {
fmt.Println(err)
}
// Convert json string to struct
var sc ServiceConfig
if err := json.Unmarshal(jsonStr, &sc); err != nil {
fmt.Println(err)
}
I have verified that tmpinterface is getting the values correctly in both the cases, but finally myconfig{} struct is empty.
tmpinterface value is:
map[%!f(string=apirouting):map[%!f(string=enablethrottling):%!f(bool=true) %!f(string=formfactor):%!f(int=4)] %!f(string=leasing):map[%!f(string=periodinsecs):%!f(int=10) %!f(string=preemptionenable):%!f(bool=false)]]
GetConfigshould accept an instance of the concrete config type, i.e.var sc ServiceConfig; GetConfig(&sc).GetConfigcode lies in the framework and various services will call it. Framework doesn't really need to know the concrete type. I am very close to my solution, its just I am not able to unmarshall it into the required struct.GetConfigdoesn't need to know the concrete type, it can acceptanyas argument, just likejson.Unmarshalorviper.Unmarshal.