go - 当值是 reflect.Ptr 时如何使用 reflect.FieldByName

标签 go reflection

我有一个 project 函数,它返回一个 slice ,其中包含输入 slice 中每个结构或映射的名称的字段值。我遇到输入 slice 包含指向结构的指针的情况。我已经设置了一个递归函数来对值进行操作,但需要知道如何将类型 reflect.Ptr 转换为底层 reflect.Struct。这是怎么做到的?任何其他设计建议表示赞赏。我对 Go 还是有点陌生​​。

代码如下:

func project(in []interface{}, property string) []interface{} {

    var result []interface{}

    var appendValue func(list []interface{}, el interface{})

    appendValue = func(list []interface{}, el interface{}) {
        v := reflect.ValueOf(el)
        kind := v.Kind()
        if kind == reflect.Ptr {

            // How do I get the struct behind this ptr?
            // appendValue(list, el)

        } else if kind == reflect.Struct {
            result = append(result, v.FieldByName(property).Interface())
        } else if kind == reflect.Map {
            result = append(result, el.(map[string]interface{})[property])
        } else {
            panic("Value must be a struct or map")
        }
    }

    for _, el := range in {
        appendValue(result, el)
    }

    return result

}

...和测试用例:

func Test_project(t *testing.T) {

    cases := map[string]struct {
        input    []interface{}
        property string
        expected []interface{}
    }{
        "simple-map": {
            []interface{}{
                map[string]interface{}{
                    "a": "a1",
                },
            },
            "a",
            []interface{}{"a1"},
        },
        "simple-struct": {
            []interface{}{
                simpleStruct{
                    A: "a1",
                },
            },
            "A",
            []interface{}{"a1"},
        },
        // THIS ONE FAILS
        "simple-struct-ptr": {
            []interface{}{
                &simpleStruct{
                    A: "a1",
                },
            },
            "A",
            []interface{}{"a1"},
        },
    }

    for k, v := range cases {

        t.Run(k, func(t *testing.T) {
            got := project(v.input, v.property)
            if !reflect.DeepEqual(got, v.expected) {
                t.Fatalf("Expected %+v, got %+v", v.expected, got)
            }
        })
    }
}

最佳答案

使用Elem()reflect.Ptr 到它指向的值。

关于go - 当值是 reflect.Ptr 时如何使用 reflect.FieldByName,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51470090/

相关文章:

go - 如何将数据 append 到嵌套结构格式化的 slice 中

go - ^ 有什么作用?

windows - 在同一个 shell Windows 中执行多个命令

go - 如何将包含错误对象的 reflect.Value 分配给错误类型的普通变量?

r - 如何相对于最后一个值镜像/反射向量

git - 如何组织具有 vendor 依赖项的 Go 项目?

json - 从types.JSON.TEXT转换为字符串列表

java - 需要在反射 get 方法中传递泛型类

reflection - BRDF 通常是如何实现的?

java - Class[] - 这是什么意思?