How Can We Modify Nested Struct Fields Using Reflection to Achieve Persistence?

Susan Sarandon
Release: 2024-10-24 12:47:31
Original
117 people have browsed it

How Can We Modify Nested Struct Fields Using Reflection to Achieve Persistence?

Using Reflection to Set Nested Struct Fields

Problem:

How can we use reflection to modify the value of a nested struct field in a way that persists?

Code:

<code class="go">type ProductionInfo struct {
    StructA []Entry
}

type Entry struct {
    Field1 string
    Field2 int
}

func SetField(source interface{}, fieldName string, fieldValue string) {
    v := reflect.ValueOf(source)
    tt := reflect.TypeOf(source)

    for k := 0; k < tt.NumField(); k++ {
        fieldValue := reflect.ValueOf(v.Field(k))

        fmt.Println(fieldValue.CanSet())
        if fieldValue.CanSet() {
            fieldValue.SetString(fieldValue.String())
        }
    }
}

func main() {
    source := ProductionInfo{}
    source.StructA = append(source.StructA, Entry{Field1: "A", Field2: 2})

    SetField(source, "Field1", "NEW_VALUE")
}</code>
Copy after login

Issues:

  1. Passing the wrong value: We're attempting to set the field of the top-level ProductionInfo struct, instead of the nested Entry struct. This causes errors because ProductionInfo does not have a Field1 field.
  2. Passing a non-pointer: Reflection cannot modify the fields of non-pointer structs. We need to pass a pointer to the Entry struct.

Solution:

  1. Modify the call to SetField to target the embedded Entry struct:

    <code class="go">SetField(source.StructA[0], "Field1", "NEW_VALUE")</code>
    Copy after login
  2. Change the function to accept and modify a pointer to the Entry:

    <code class="go">func SetField(source *Entry, 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)
     }
    }</code>
    Copy after login

Final Code:

<code class="go">package main

import (
    "fmt"
    "reflect"
)

type ProductionInfo struct {
    StructA []Entry
}

type Entry struct {
    Field1 string
    Field2 int
}

func SetField(source *Entry, fieldName string, fieldValue string) {
    v := reflect.ValueOf(source).Elem()

    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])
}</code>
Copy after login

Output:

Before:  {A 2}
true
After:  {NEW_VALUE 2}
Copy after login

The above is the detailed content of How Can We Modify Nested Struct Fields Using Reflection to Achieve Persistence?. For more information, please follow other related articles on the PHP Chinese website!

source:php
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!