package patient import ( "reflect" "strings" ) func SetPatient(dst, src interface{}, preserve map[string]bool) { dv := reflect.ValueOf(dst).Elem() sv := reflect.ValueOf(src).Elem() for i := 0; i < dv.NumField(); i++ { f := dv.Type().Field(i) fieldName := f.Name // skip preserved fields if preserve[fieldName] { continue } df := dv.Field(i) sf := sv.Field(i) if !df.CanSet() { // skip unexported skip continue } switch df.Kind() { case reflect.Struct: nestedPreserve := map[string]bool{} for key := range preserve { if strings.HasPrefix(key, fieldName+".") { nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true } } SetPatient(df.Addr().Interface(), sf.Addr().Interface(), nestedPreserve) case reflect.Pointer: // Check if pointer points to a struct if df.Type().Elem().Kind() == reflect.Struct { if sf.IsNil() { break } // If dest pointer is nil, allocate it if df.IsNil() { df.Set(reflect.New(df.Type().Elem())) } // Recurse into struct via Elem() nestedPreserve := map[string]bool{} for key := range preserve { if strings.HasPrefix(key, fieldName+".") { nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true } } SetPatient(df.Elem().Addr().Interface(), sf.Elem().Addr().Interface(), nestedPreserve) } default: // Overwrite only when src has non-zero value if !sf.IsZero() { df.Set(sf) } } } }