Ich implementiere Teilupdate für eine Entität.Aktualisieren von Struct-Feld mit Reflektion
Das Unternehmen Struktur sieht aus wie
type Entity struct {
Id string `readonly:"true"`
Spec EntitySpec
Status EntityState
}
type EntitySpec struct {
Version *string `readonly:"true"`
Users []*User
Field1 *InnerStruct1
Field2 []*InnerStruct2
}
und so weiter.
So Entity
struct Felder Felder rekursiv und Update iterieren Ich versuche Reflexion zu verwenden, die Benutzer zu aktualisieren erlaubt ist:
func method(existingEntity interface{}, newEntity interface{}) {
entityType := reflect.TypeOf(existingEntity)
logger.Debugf("type: %v", entityType)
for i := 0; i < entityType.NumField(); i++ {
value := entityType.Field(i)
logger.Debugf("Name: %s", value.Name)
tag := value.Tag
logger.Debugf("tag: %s", tag)
if tag.Get("readonly") == "true" {
logger.Debugf("readonly, go to next one")
continue
}
oldField := reflect.Indirect(reflect.ValueOf(existingEntity).Field(i))
newField := reflect.Indirect(reflect.ValueOf(newEntity).FieldByName(value.Name))
logger.Debugf("type: %v", value.Type.Kind())
if value.Type.Kind() == reflect.Struct {
logger.Debugf("value: %v", oldField)
//struct, go into it
method(oldField.Interface(), newField.Interface())
} else {
if oldField != newField && oldField.String() != newField.String() {
logger.Debugf("Type of old field: %v", oldField.Type())
logger.Debugf("Type of new field: %v", newField.Type())
logger.Debugf("Update: %v \nTo %v", oldField, newField)
oldField.Set(newField) //HERE I get the exception
} else {
logger.Debugf("Field values are equal")
}
}
}
}
Aber wenn ich versuche, einen neuen Wert mit oldField.Set(newField)
zuweisen, ich erhalte eine Ausnahme:
reflect: reflect.Value.Set using unaddressable value
ich auch reflect.ValueOf(existingEntity).Field(i).Set(reflect.ValueOf(newEntity).FieldByName(value.Name))
aber bekam die gleiche Ausnahme ausprobiert habe.
Können Sie mir erklären, warum es passiert und wie Sie das beheben können?
Vielen Dank, Ihre Lösung funktioniert für diesen Fall. Allerdings habe ich festgestellt, dass das Ding im Allgemeinen komplizierter ist: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/conversion/cloner.go – dds