如何使用少一个属性动态创建结构?

时间:2018-04-05 20:24:30

标签: go reflection

有没有办法复制通用结构(即属性名称未知的结构)并跳过一个已知属性?

以下是我所知道的:

  • 我的函数的参数 - 我将调用参数myData - 属于interface{}类型。
  • myData是一个结构。
  • myData有一个已知属性path
  • myData有大约0到6个左右的其他属性,其中没有一个是先验已知的。
  • 删除path属性后,“剩余”就是30种可能的结构类型之一。

所以我想从path中删除myData(或者更准确地创建一个省略path的副本),以便生成的代码尝试将结构强制转换为一个其可能的类型将能够成功。

我找到了通过反射复制结构的示例,但它们通常会创建一个相同底层类型的空结构,然后将其填入。所以甚至可以删除属性,因为我概述了......?

1 个答案:

答案 0 :(得分:1)

您可以使用reflect.StructOf从字段列表中动态创建结构。

package main

import (
    "fmt"
    "reflect"
)

type A struct {
    Foo string
    Bar int
    Baz bool // to be skipped
}

type B struct {
    Foo string
    Bar int
}

func main() {
    av := reflect.ValueOf(A{"hello", 123, true})

    fields := make([]reflect.StructField, 0)
    values := make([]reflect.Value, 0)
    for i := 0; i < av.NumField(); i++ {
        f := av.Type().Field(i)
        if f.Name != "Baz" {
            fields = append(fields, f)
            values = append(values, av.Field(i))
        }
    }

    typ := reflect.StructOf(fields)
    val := reflect.New(typ).Elem()
    for i := 0; i < len(fields); i++ {
        val.Field(i).Set(values[i])
    }

    btyp := reflect.TypeOf(B{})
    bval := val.Convert(btyp)

    b, ok := bval.Interface().(B)
    fmt.Println(b, ok)
}