【问题标题】:Storing Configuration structs in an Interface{} and casting it back to original struct在 Interface{} 中存储配置结构并将其转换回原始结构
【发布时间】:2021-12-21 11:01:12
【问题描述】:

我想做什么

我为Apps 写了一个模板 每个App 都有一个配置 - 因此我想将Config 存储到App struct 的属性中。
我所有的configs 都存储在JSON - 因此我想提供一个通用的func 来加载JSON

const JSON = `{
  "Name": "TestConfig"
}`

注意:我尝试使用和不使用指针来解决我的问题,两者都会导致相同的错误消息 - 两个版本都包含在下面。

所以让我们把 App-Template 当作:

type App struct {
    config    interface{}
    configPtr *interface{} 
}

还有一个Configuration:

// ConfigurationA is an actual implementation of the Config (Application A)
type ConfigurationA struct {
    Name string
    // ... add more properties here
}

我还实现了一个func 以从file 加载Config 并将其存储在App

func (a *App) GeneralConfigLoader(jsonData string, v interface{}) (err error) {
    // load json -> struct
    err = json.Unmarshal([]byte(jsonData), &v)
    if err != nil {
        fmt.Println("error unmarshalling JSON data")
        return err
    }
    a.config = v
    a.configPtr = &v
    return nil
}

由于我有一个具有一般负载 func 的应用程序,现在应该可以创建一个简单的 func 以将空接口转换为正确的配置结构。

// Config - Config of the App
func Config(a *App) *ConfigurationA {
    var cfg ConfigurationA = a.config.(ConfigurationA)
    return &cfg
}

// ConfigPtr - Config of the App
func ConfigPtr(a *App) *ConfigurationA {
    var i interface{} = *a.configPtr
    return i.(*ConfigurationA)
}

如果我将其总结为一个可执行文件,例如:

func main() {
    var conf ConfigurationA // the interface used as Configuration
    var a = &App{}
    a.GeneralConfigLoader(JSON, conf)

    //panics: interface conversion: interface {} is map[string]interface {}, not main.ConfigurationA
    var cfg = Config(a)
    fmt.Println("cfg -> ", cfg)

    //panics: interface conversion: interface {} is map[string]interface {}, not *main.ConfigurationA
    var cfgPtr = ConfigPtr(a)
    fmt.Println("cfgPtr -> ", cfgPtr)
}

应用程序崩溃(上一节中的 cmets...)

为什么go会省略类型信息?

或者更好...为什么我不能将配置转换回原来的样子,因为我知道它是什么...?

通知

如果我不使用这个通用加载器并创建具体的实现,它确实可以工作!

问题:

我做错了什么?
使用 go 是不可能的(怀疑)?

【问题讨论】:

  • 解组到*interface{} 将始终导致基础值为map[string]interface{}[]interface{} 或标量之一。您应该使用指向目标类型的指针的基础值解组到 interface{}

标签: json go


【解决方案1】:

传递一个指向 GeneralConfigLoader 的指针。解组该指针。删除字段App.configPtr。它没有用,也没有达到您的预期。

func (a *App) GeneralConfigLoader(jsonData string, v interface{}) (err error) {
    err = json.Unmarshal([]byte(jsonData), v) // & removed here
    if err != nil {
        fmt.Println("error unmarshalling JSON data")
        return err
    }
    a.config = v
    return nil
}

func Config(a *App) *ConfigurationA {
    return a.config.(*ConfigurationA)
}

像这样加载配置:

var config ConfigurationA
var a = &App{}
a.GeneralConfigLoader(JSON, &config) // & added here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 2012-11-26
    • 2019-05-12
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多