Using reflection SetString

前端 未结 1 597
旧时难觅i
旧时难觅i 2021-01-24 05:48

I have a struct like this one:

type ProductionInfo struct {
    StructA []Entry
}

type Entry struct {
    Field1 string
    Field2 int
}

I wou

相关标签:
1条回答
  • 2021-01-24 06:05

    Multiple errors. Let's iterate over them.

    First, you pass a value of ProductionInfo and not a value of Entry whose field you want to modify, so first change it to:

    SetField(source.StructA[0], "Field1", "NEW_VALUE")
    

    Next, you are passing a (non-pointer) value. You can't modify the fields of a non-pointer struct with reflection, because that would only modify a copy which would be discarded. In order to avoid this (and further confusion), this is not allowed (CanSet() returns false). So you have to pass a pointer to the struct:

    SetField(&source.StructA[0], "Field1", "NEW_VALUE")
    

    Now inside SetField() the reflect.ValueOf(source) will describe the passed pointer. You may use Value.Elem() to navigate to the reflect.Value of the pointed object (the struct value):

    v := reflect.ValueOf(source).Elem()
    

    And now it works. Modified code:

    func SetField(source interface{}, fieldName string, fieldValue string) {
        v := reflect.ValueOf(source).Elem()
    
        fmt.Println(v.FieldByName(fieldName).CanSet())
    
        if v.FieldByName(fieldName).CanSet() {
            v.FieldByName(fieldName).SetString(fieldValue)
        }
    }
    
    func main() {
        source := ProductionInfo{}
        source.StructA = append(source.StructA, Entry{Field1: "A", Field2: 2})
    
        fmt.Println("Before: ", source.StructA[0])
        SetField(&source.StructA[0], "Field1", "NEW_VALUE")
        fmt.Println("After: ", source.StructA[0])
    }
    

    Output (try it on the Go Playground):

    Before:  {A 2}
    true
    After:  {NEW_VALUE 2}
    
    0 讨论(0)
提交回复
热议问题