【问题标题】:How to pass a pointer of struct field in mapstructure.decode如何在 mapstructure.decode 中传递结构字段的指针
【发布时间】:2018-09-11 10:46:51
【问题描述】:

我正在尝试借助 mapstructure 库将地图解码为结构类型。如果我使用普通变量进行解码,它可以解码,但如果我传递 struct 字段,它不会解码地图:

package main

import (
    "github.com/mitchellh/mapstructure"
)

type Person struct {
    Name string
}

type Bundle struct {
    Name string
    Struct interface{}
}

func main() {
    p_map := map[string]string{
        "Name": "John",
    }

    p := Person{}
    mapstructure.Decode(p_map, &p)

    print(p.Name) // shows name John

    b := Bundle{
        "person"
        Person{},
    }

    mapstructure.Decode(p_map, &b.Struct)

    print(b.Struct.(Person).Name) // Does not show any name. Blank

}

您能否澄清一下我是否为地图解码传递了错误的存储空间,或者这只是地图结构的限制,我无法将地图解码为结构字段?谢谢!

UPD

如果我对我需要使用这种流程的实际原因不够清楚,我很抱歉:

我向不同的资源发送 HTTP 请求并获取具有不同字段的各种对象,因此最初我将它们收集为interface{}。获得特定资源对象后,我需要将其转换为特定结构(在我的示例中为Person),因此我使用mapstructure.decode() 函数。

由于我有各种以不同结构解码的对象,我想创建一个循环以避免代码重复。我想做的是创建一个具有不同结构的切片,例如:

bundles := []Bundle{
    {"person", Person{}}
    {"employee", Employee{}}
    ...
}

然后循环解码对象:

for bundle := range bundles {
    // map_storage contains different type maps that are going to be decoded into struct and key for the specific object is bundle name
    mapstructure.Decode(maps_storage[bundle.Name], &bundle.Struct)

    // bundle.Struct blank, but I expect that it is filled as in the example below
}

【问题讨论】:

    标签: go


    【解决方案1】:

    我认为你必须稍微改变一下实现

    var p1 Person
    
    mapstructure.Decode(p_map, &p1)
    b := Bundle{
        p1,
    }
    
    print(b.Struct.(Person).Name) // John will appear
    

    我正在尝试上面的代码,但导致Person 为空。也许Decode 函数不能改变b.Struct 的实际值(我不确定确切的原因,这只是我的看法),但如果我先解码为结构Person 然后分配给Bundle 就可以了。

    更新: 通过一些研究,我发现了问题。您必须使用指针而不是结构。这里是更新的代码

    package main
    
    import (
        "github.com/mitchellh/mapstructure"
    )
    
    type Person struct {
        Name string
    }
    
    type Bundle struct {
        Name   string
        Struct interface{}
    }
    
    func main() {
        p_map := map[string]string{
            "Name": "John",
        }
    
        p := &Person{}
        mapstructure.Decode(p_map, &p)
    
        print(p.Name) // shows name John
    
        b := Bundle{
            "person",
            &Person{},
        }
    
        mapstructure.Decode(p_map, &b.Struct)
    
        print(b.Struct.(*Person).Name) // Does not show any name. Blank
    
    }
    

    【讨论】:

    • 感谢您的回答。恐怕在分配给结构之前我无法做到这一点。我更新了我的问题。
    • @Eduard 我也更新了答案。请看一下。
    • 谢谢 Moch,这正是我所需要的!
    【解决方案2】:

    将 Bundle 中的 Struct 字段类型从 interface{} 更改为 Person 后,它对我有用。

    type Bundle struct {
        Struct Person
    }
    print(b.Struct.Name)
    

    【讨论】:

    • 不幸的是,我必须使用这个属性作为接口,因为我要设置它的许多不同结构类型的实例,然后将它作为一个循环使用
    猜你喜欢
    • 1970-01-01
    • 2019-03-30
    • 2013-09-02
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多