简体   繁体   English

如何使用反射将值分配给嵌套结构

[英]how to assign value to nested struct using reflect

***see updated field at the bottom,please**** ***请参阅底部的更新字段,请****

I want to assign a value to a nested struct but it does not work: 我想为嵌套结构分配一个值,但它不起作用:

try code here 在这里尝试代码

 type MyStruct2 struct {
    Value3 string
}
type myStruct1 struct {
    Value1    string
    Value2    int
    MyStruct2 MyStruct2
}

func main() {
    var ah myStruct1 
    t := reflect.TypeOf(ah)
    where := reflect.ValueOf(&ah).Elem()

    rt0 := t.Field(0)
    field0 := where.FieldByIndex(rt0.Index)
    field0.SetString("hello") 

    rt1 := t.Field(1)
    field1 := where.FieldByIndex(rt1.Index)
    field1.SetInt(4)

    rt2 := t.Field(2)
    rt2_1:=rt2.Type.Field(0)
    field2 := where.FieldByIndex(rt2_1.Index)
    field2.SetString("hello2")//not assigning to struct

    fmt.Printf("%+v\n",ah)
}

output: {Value1:hello2 Value2:4 MyStruct2:{Value3:}} 输出:{Value1:hello2 Value2:4 MyStruct2:{Value3:}}

As you can see, it's not assigning a value to the nested struct 如您所见,它没有为嵌套结构分配值

// update: //更新:

as @Austin said this is solved by using: 正如@Austin所说的,可以通过使用以下方法解决:

field2 :=where.FieldByIndex(rt2.Index).FieldByIndex(rt2_1.Index)

instead, but it's not working inside function: 而是在函数内部不起作用:

try code here 在这里尝试代码

type MyStruct2 struct {
    Value3 string
}
type myStruct1 struct {
    Value1    string
    Value2    string
    MyStruct2 MyStruct2
}

func main() {
    var ah myStruct1
    t := reflect.TypeOf(ah)
    where := reflect.ValueOf(&ah).Elem()
    max := t.NumField()
    for i := 0; i < max; i++ {
        f := t.Field(i)
        findAssing("hello", f, where)
    }
    fmt.Printf("%+v\n", ah)
}

func findAssing(me string, rt reflect.StructField, field reflect.Value) {
    if rt.Type.Kind() == reflect.Struct {
        max := rt.Type.NumField()
        for i := 0; i < max; i++ {
            if rt.Type.Field(i).Type.Kind() == reflect.Struct {
                field = field.FieldByIndex(rt.Type.Field(i).Index)
            }
            findAssing(me, rt.Type.Field(i), field)
        }
    } else {
        field = field.FieldByIndex(rt.Index)
        field.SetString("hello")
    }
}

You need to select the third field of the outer struct before you select the first field of the inner struct. 在选择内部结构的第一个字段之前,需要选择外部结构的第三个字段。 Ie, 也就是说,

rt2 := t.Field(2)
rt2_1 := rt2.Type.Field(0)
field2 := where.FieldByIndex(rt2.Index).FieldByIndex(rt2_1.Index)
field2.SetString("hello2") // Will assign to the inner struct now.

Edit: The code in the edited question makes a similar mistake in that it does not fetch the field of the outer struct first. 编辑:已编辑问题中的代码犯了类似的错误,因为它没有先获取外部结构的字段。 Additionally, it overrides the value of field repeatedly in a way that probably doesn't do what is intended. 此外,它以可能无法实现预期目的的方式反复覆盖field的值。 Something like this should work: 这样的事情应该起作用:

func findAssing(me string, rt reflect.StructField, field reflect.Value) {
    subField := field.FieldByIndex(rt.Index)
    if rt.Type.Kind() == reflect.Struct {
        max := rt.Type.NumField()
        for i := 0; i < max; i++ {
            findAssing(me, rt.Type.Field(i), subField)
        }
    } else {
        subField.SetString("hello")
    }
}

If your goal is recursively set all string fields to some value, then use the following code. 如果您的目标是将所有字符串字段递归设置为某个值,请使用以下代码。 You don't say what the code is supposed to do, so this is just a guess. 您没有说代码应该做什么,所以这只是一个猜测。

func main() {
    var ah myStruct1
    setStringsInStruct("hello", reflect.ValueOf(&ah).Elem())
    fmt.Printf("%+v\n", ah)
}

func setStringsInStruct(s string, v reflect.Value) {
    t := v.Type()
    for i := 0; i < t.NumField(); i++ {
        sf := t.Field(i)
        switch sf.Type.Kind() {
        case reflect.Struct:
            setStringsInStruct(s, v.Field(i))
        case reflect.String:
            v.Field(i).SetString(s)
        }
    }
}

https://play.golang.org/p/YVjMpk1qMtb https://play.golang.org/p/YVjMpk1qMtb

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM