英文:
convert interface to defined struct Golang
问题
我正在处理一个实用方法,假设叫做GetConfig(),它读取配置结构并将其返回给调用者。GetConfig() 不知道要读取的配置是什么,但调用者知道它将接收到的结构。
为此,我编写了下面的实用程序:
=========== yaml 文件数据 ==========
apiRouting:
enableThrottling: true
formFactor: 4
leasing:
periodInSecs: 10
preemptionEnable: false
=========== yaml 文件数据 ==========
func GetConfig() (interface{}, error) {
fmt.Println("正在读取通用服务配置")
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
}
调用者使用 GetConfig() 如下:(我尝试了两种选项,但都没有成功)
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"`
}
// 代码片段 [选项 1]
tmpinterface := GetConfig()
myconfig, ok := tmpinterface.(ServiceConfig)
if !ok {
log.Fatal()
} else {
println(myconfig)
}
// 代码片段 [选项 2]
tmpinterface := GetConfig()
// 将 map 转换为 JSON 字符串
jsonStr, err := json.Marshal(tmpinterface)
if err != nil {
fmt.Println(err)
}
// 将 JSON 字符串转换为结构体
var sc ServiceConfig
if err := json.Unmarshal(jsonStr, &sc); err != nil {
fmt.Println(err)
}
我已经验证了在这两种情况下 tmpinterface
正确地获取了值,但最终 myconfig{}
结构体是空的。
tmpinterface
的值是:
map["apirouting"]:map["enablethrottling":true "formfactor":4] "leasing":map["periodinsecs":10 "preemptionenable":false]
英文:
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)]]
答案1
得分: 1
@mkopriva,感谢您提供了一个更简洁的解决方案。
func GetConfig(appConfig any) error {
fmt.Println("读取通用服务配置")
viper.SetConfigName("service_config")
viper.AddConfigPath("config/default")
if err := viper.ReadInConfig(); err != nil {
return err
}
if err := viper.Unmarshal(appConfig); err != nil {
return err
}
return nil
}
func main() {
var sc ServiceConfig
if err := GetConfig(&sc); err != nil {
panic(err)
}
fmt.Println(sc)
}
英文:
@mkopriva, thanks for a cleaner solution.
func GetConfig(appConfig any) error {
fmt.Println("reading generic service config")
viper.SetConfigName("service_config")
viper.AddConfigPath("config/default")
if err := viper.ReadInConfig(); err != nil {
return err
}
if err := viper.Unmarshal(appConfig); err != nil {
return err
}
return nil
}
func main() {
var sc ServiceConfig
if err := GetConfig(&sc); err != nil {
panic(err)
}
fmt.Println(sc)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论