将接口转换为定义结构Golang

x33g5p2x  于 2022-12-07  发布在  Go
关注(0)|答案(1)|浏览(123)

我正在开发一个实用程序方法,比如说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)]]
mcvgt66p

mcvgt66p1#

@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)
}

相关问题