"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 Overcome SetCan() Always Returning False When Setting Struct Field Values Using Reflection?

How to Overcome SetCan() Always Returning False When Setting Struct Field Values Using Reflection?

Published on 2024-11-09
Browse:463

How to Overcome SetCan() Always Returning False When Setting Struct Field Values Using Reflection?

Exploring Reflection with SetString for Structs

Reflection provides powerful tools for manipulating Go structures dynamically. In this example, we encounter a common issue when attempting to set the value of a struct field using reflection: CanSet() always returns false. This hindrance prevents field modifications, leaving us in a quandary.

Identifying the Pitfalls

The provided code snippet highlights two fundamental errors:

  1. Passing a value instead of a pointer: Structs by value cannot be modified through reflection. Instead, we must pass a pointer to the struct, ensuring that any changes are applied to the actual object.
  2. Incorrect element targeting: The code initially operates on the entire ProductionInfo struct rather than the specific Entry whose Field1 value needs to be changed. To rectify this, we need to focus on the desired Entry element.

Resolving the Issues

After addressing these pitfalls, we can refine our code:

func SetField(source interface{}, fieldName string, fieldValue string) {
    v := reflect.ValueOf(source).Elem() // Obtain the value of the pointed object
    fmt.Println(v.FieldByName(fieldName).CanSet())
    if v.FieldByName(fieldName).CanSet() {
        v.FieldByName(fieldName).SetString(fieldValue)
    }
}

In the modified SetField() function, we:

  1. Use Elem() to navigate to the value of the pointed object, ensuring we operate on the actual struct.
  2. Use FieldByName() to access the specific field we want to modify.

Code in Action

With these modifications, the code now successfully updates the Field1 value:

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:

Before:  {A 2}
true
After:  {NEW_VALUE 2}

The result showcases the successful modification of Field1 within the Entry struct.

Release Statement This article is reprinted at: 1729662680 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