"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > How to Use Reflection to Modify Struct Fields with CanSet() and Structs?

How to Use Reflection to Modify Struct Fields with CanSet() and Structs?

Published on 2024-11-09
Browse:693

How to Use Reflection to Modify Struct Fields with CanSet() and Structs?

Using Reflection to Modify Struct Fields: CanSet() and Structs

When using reflection to modify struct fields, it's important to understand the principles behind field accessibility and modification.

CanSet() for Structs

In your example, you encountered CanSet() returning false for struct fields. This is because by default, Go does not allow modifying non-exported (private) fields of a struct using reflection. This is a security measure to prevent accidental or malicious modification of internal struct state.

Addressing the Issues

To set the values of struct fields using reflection, consider the following steps:

  1. Modify a Value: When calling your SetField() function, pass the pointer to the struct, not the struct value itself. This allows you to modify the actual struct, not a copy.
  2. Use Value.Elem() for Pointers: If you pass a pointer to the struct, you need to use reflect.ValueOf(source).Elem() to obtain the reflect.Value of the pointed struct. This navigates to the actual struct value.
  3. Use FieldByName for Field Access: Instead of looping through all fields in the struct, use v.FieldByName(fieldName) to access the specific field you want to modify. This ensures you're accessing the correct field and is more efficient.

Modified Code

Here's the modified code that addresses the issues:

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])
}

This code will now successfully modify the Field1 value of the Entry struct.

Release Statement This article is reprinted at: 1729741550 If there is any infringement, please contact [email protected] to delete it
Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3