I have created Casedetail1 struct in that i have another struct kit details. I need to update KitStatus and KitOwner while pass updated value from main function. Once nested struct is updated I am trying to fetch the parent struct (Casedetail1) to see the updated output. While trying to run the below code in playground it gives me { []} as output. I am getting no value.
package main
import (
"fmt"
"reflect"
)
type CaseDetails1 struct {
ObjectType string `json:"docType"`
CaseID string `json:"caseID"`
CaseStatus string `json:"caseStatus"`
KitDetails []Kit_Details `json:"kit_Details"`
}
type Kit_Details struct {
KitID string `json:"kitID"`
KitStatus string `json:"kitStatus"`
KitTimestamp string `json:"kittimestamp"`
KitSerialID string `json:"kitSerialID"`
KitOwner string `json:"kitOwner"`
}
// Function to update existing field of a nested struct
func method(existingEntity interface{}, newEntity interface{}) {
entityType := reflect.TypeOf(existingEntity).Elem()
for i := 0; i < entityType.NumField(); i++ {
value := entityType.Field(i)
value1 := entityType.Field(i).Name
fmt.Println(value1)
tag := value.Tag
if tag.Get("readonly") == "true" {
continue
}
oldField := reflect.ValueOf(existingEntity).Elem().Field(i)
newField := reflect.ValueOf(newEntity).FieldByName(value.Name)
//fmt.Println(newField)
if value.Type.Kind() == reflect.Struct {
method(oldField.Addr().Interface(), newField.Interface())
} else {
if value1 == "KitStatus" || value1 == "KitTimestamp" {
fmt.Println(value1)
oldField.Set(newField)
}
}
}
}
func main() {
var a CaseDetails1
b := CaseDetails1{"casedetails", "456", "OPEN", []Kit_Details{Kit_Details{"789",
"IN_PROGRESS","2019-10-30","345","HOSPITAL"},},}
method(&a, b)
fmt.Println(a)
}
You indicate that CaseDetails1 has another struct kit details. But it appears it’s not a struct but a slice. The code inside “method” is explicitely targeted to structs not slices. Have a nice day.
I have declared as struct but it indicates as slice. If I want to access kit details struct what all need to change in that code. Please help me on this.
This is sample case details
{
“docType”: “caseDetails”,
“caseID”: “456”,
“caseStatus”: “OPEN”,
“kit_Details”: [
{
“KitTimestamp”: “2019-10-25T10:10:03.029Z”,
“docType”: “kitDetails”,
“kitID”: “789”,
“kitSerialID”: “12345”,
“kitStatus”: “OPEN”
“kitOwner”: “OEM”,
},
{
“KitTimestamp”: “2019-10-25T10:10:03.029Z”,
“docType”: “kitDetails”,
“kitID”: “790”,
“kitOwner”: “DIST”,
“kitSerialID”: “123456”,
“kitStatus”: “IN_Progress”
}
]
}
I want to update “Kitstatus” and “KitTimestamp” for “kitID”: “789”
For that if i use method function, and pass all the arguments to method() , can it update kitstatus and kittimestamp filed.
My goal is to update fields in Kit_Details struct.Overwrite old value of kit details struct fields with new value passed using method function.
I hope it will more clear to you. Please let me know if you need more details.Thanks
You don’t need to pass arguments as interface{} and don’t need to use reflect.
You need to pass tow pointers to the struct to method:
func method(a, b * CaseDetails1)
You don’t explain what kind of update you want to do. Here are some hints
len(a.KitDetails) will return the number of KitDetails elements in the slice
a.KitDetails[i].KitStatus = ... will assign … to the KitStatus field of the KitDetails i. Replace i with a number like 0 or 1 for instance to access KitDetails 0 or 1.
Here is a better although incomplete solution of your problem. At least, it shows you how to deal with slices. But as Christophe already said, there’s still much work to do …
package main
import (
"fmt"
"reflect"
)
type CaseDetails1 struct {
ObjectType string `json:"docType"`
CaseID string `json:"caseID"`
CaseStatus string `json:"caseStatus"`
KitDetails []Kit_Details `json:"kit_Details"`
}
type Kit_Details struct {
KitID string `json:"kitID"`
KitStatus string `json:"kitStatus"`
KitTimestamp string `json:"kittimestamp"`
KitSerialID string `json:"kitSerialID"`
KitOwner string `json:"kitOwner"`
}
// Function to update existing field of a nested struct
func method(existingEntity interface{}, newEntity interface{}) {
entityType := reflect.TypeOf(existingEntity).Elem()
for i := 0; i < entityType.NumField(); i++ {
value := entityType.Field(i)
value1 := entityType.Field(i).Name
fmt.Println(value1, "=", value)
tag := value.Tag
if tag.Get("readonly") == "true" {
continue
}
oldField := reflect.ValueOf(existingEntity).Elem().Field(i)
newField := reflect.ValueOf(newEntity).FieldByName(value.Name)
if value.Type.Kind() == reflect.Slice {
newSlice := reflect.MakeSlice(value.Type, newField.Len(), newField.Len())
oldField.Set(newSlice)
n := reflect.Copy(oldField, newField)
fmt.Println("N=", n)
//method(oldField.Addr().Interface(), newField.Interface())
} else {
if value1 == "KitStatus" || value1 == "KitTimestamp" {
oldField.Set(newField)
}
}
}
}
You should notice that I commented the recursive call of method because it is inadapted in the general case (uncomment it and you will see). Have a nice day.
Note that the time stamp has a weird value because of the clock on the playground computer. If you run this code on your computer, the time will be correct.