提问人:Hemant Yadav 提问时间:12/5/2022 更新时间:12/5/2022 访问量:102
将接口转换为定义的结构 Golang
convert interface to defined struct Golang
问:
我正在研究一个实用程序方法,比如说 GetConfig(),它读取配置结构并将其返回给调用者。GetConfig() 不知道它将读取什么配置,但调用者知道结构体将接收什么。
在这方面,我编写了一个以下实用程序:
=========== 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
}
调用者像这样使用 GetConfig():(我尝试了 2 个选项,没有任何效果)
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)
}
我已经验证了在这两种情况下都正确获取了值,但最终结构为空。tmpinterface
myconfig{}
tmpinterface
值为:
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赞
Hemant Yadav
12/5/2022
#1
@mkopriva,感谢您提供更清洁的解决方案。
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)
}
评论
GetConfig
应该接受具体配置类型的实例,即 .var sc ServiceConfig; GetConfig(&sc)
GetConfig
GetConfig
不需要知道具体类型,它可以接受作为参数,就像 or 一样。any
json.Unmarshal
viper.Unmarshal