我正在使用一个API,我需要向它传递一段 struct . 我有一片映射,所以我需要将它转换为一片 struct .

package main

import "fmt"

func main() {
    a := []map[string]interface{}{}
    b := make(map[string]interface{})
    c := make(map[string]interface{})
    
    b["Prop1"] = "Foo"
    b["Prop2"] = "Bar"
    a = append(a, b)

    c["Prop3"] = "Baz"
    c["Prop4"] = "Foobar"
    a = append(a, c)

    fmt.Println(a)
}

[Map[Prop1:Foo Prop2:Bar]贴图[Prop3:Baz Prop4:Foobar]

因此,在本例中,我有映射a的切片,其中包含bc,它们是具有不同键的字符串的映射.

我希望将a转换为 struct 片段,其中第一个元素是以Prop1Prop2为属性的 struct ,第二个元素是以Prop3Prop4为属性的 struct .

这个是可能的吗?

我看过https://github.com/mitchellh/mapstructure个,但我不能让它在我的用例中工作.我看过这个答案: https://stackoverflow.com/a/26746461/3390419

它解释了如何使用该库:

Mapstructure.Decode(mydata,&Result)

然而,这似乎假设result是实例的 struct 是预定义的,而在我的例子中, struct 是动态的.

推荐答案

您可以做的是首先分别循环遍历每个映射,使用每个映射的键-值对构造一个包含reflect.StructField个值的相应切片.一旦准备好这样的切片,就可以将其传递给reflect.StructOf,这将返回表示动态 struct 类型的reflect.Type值,然后可以将其传递给reflect.New以创建reflect.Value,它将表示动态 struct 的实例(实际上是指向 struct 的指针).

例如.

var result []any
for _, m := range a {
    fields := make([]reflect.StructField, 0, len(m))

    for k, v := range m {
        f := reflect.StructField{
            Name: k,
            Type: reflect.TypeOf(v), // allow for other types, not just strings
        }
        fields = append(fields, f)
    }

    st := reflect.StructOf(fields) // new struct type
    sv := reflect.New(st)          // new struct value

    for k, v := range m {
        sv.Elem(). // dereference struct pointer
                FieldByName(k).         // get the relevant field
                Set(reflect.ValueOf(v)) // set the value of the field
    }

    result = append(result, sv.Interface())
}

https://go.dev/play/p/NzHQzKwhwLH

Go相关问答推荐

ChromeDriver不存在(高朗selenium)

从使用Golang otelmux检测的Otel跟踪中获取trace_id

我可以扫描表中每个项目的最高范围键值吗?

如何在golang中使用viper获取对象的配置数组?

用于提取 <*n 的正则表达式(其中 n 是一个数字)

Opensearch 错误 ping 弹性服务器:由未知权威签署的 x509 证书

如何使用 sync.WaitGroup 来执行所有的 goroutine?

gopacket:IP-in-IP 数据包上的解码层

在密钥不存在时处理 PATCH 部分更新

具有嵌套重复的正则表达式

有没有办法约束(通用)类型参数?

如果 transaction.Commit 对带有 postgres 连接的 SQL 失败,您是否需要调用 transaction.RollBack

从 Makefile 运行时权限被拒绝

在 docker kill --signal=SIGX 上以这种方式关闭容器内运行的 go 应用程序是否安全?

在 go 中将运行命令的标准输出发送到其标准输入

合并几千万文件最快的方法是什么

行之间的模板交替设计

在 Go 中表达函数的更好方法( struct 方法)

如何在程序退出时使用 golang 删除文件?

Golang 修改没有struct的 json