I wanted a way to selectively copy Go fields from one struct to another. This allows me to update data from one struct to another without changing certain information. Here's the solution I came up with. It depends on setting a tag field of "update". Would appreciate any feedback for making this more robust or better or maybe why this is just a bad idea to begin with.
import (
"errors"
"fmt"
"reflect"
)
func UpdateStruct(src, dst interface{}) error {
if reflect.TypeOf(src) != reflect.TypeOf(dst) {
return errors.New("structs not of same type")
}
if reflect.ValueOf(src).Kind() != reflect.Ptr {
return errors.New("arguments must be pointers")
}
srcVal := reflect.ValueOf(src).Elem()
srcType := srcVal.Type()
dstVal := reflect.ValueOf(dst).Elem()
for i := 0; i < srcVal.NumField(); i++ {
s := srcType.Field(i)
if tag := s.Tag.Get("update"); tag == "" {
continue
}
fieldName := srcType.Field(i).Name
d := dstVal.FieldByName(fieldName)
if d.IsValid() {
if d.CanSet() {
d.Set(srcVal.Field(i))
} else {
return fmt.Errorf("cannot set field: %s", fieldName)
}
} else {
return fmt.Errorf("invalid field: %s", fieldName)
}
}
return nil
}
example struct:
type Tester struct {
ID string
Name string `update:"true"`
Date time.Time `update:"true"`
Decimal float64 `update:"true"`
Number int `update:"true"`
CaseID uuid.UUID `update:"true"`
}