Skip to content

Instantly share code, notes, and snippets.

@fenos
Created April 25, 2019 10:15
Show Gist options
  • Save fenos/ddeac979a9d65c653b5c3684aacd70c1 to your computer and use it in GitHub Desktop.
Save fenos/ddeac979a9d65c653b5c3684aacd70c1 to your computer and use it in GitHub Desktop.
Merge 2 generic structs values
package structs
import "reflect"
// obj1 := struct{ ID string Name string }
// obj2 := struct{ ID string Name string }{ ID: "1", Name: "Jhon" }
//
// merged := merge.Structs(obj1, obj2)
//
// merge => struct{ ID string Name string }{ ID: "1", Name: "Jhon" }
//
func Structs(baseStruct interface{}, fromValues interface{}) interface{} {
fieldNames := getFieldsName(baseStruct)
pointerBaseStruct := interfacePointer(baseStruct)
fromPtr := interfacePointer(fromValues)
for parentIndex, fieldName := range fieldNames {
keyIndex := hasKey(fieldName, fromValues)
if keyIndex != -1 {
setInterfaceValue(
reflect.Indirect(pointerBaseStruct).Field(parentIndex),
reflect.Indirect(fromPtr).Field(keyIndex),
)
}
}
return pointerBaseStruct.Elem().Interface()
}
func getFieldsName(a interface{}) ( fields []string ) {
val := interfacePointer(a)
elem := val.Elem()
for i:=0; i<elem.NumField();i++{
fields = append(fields, elem.Type().Field(i).Name)
}
return fields
}
// https://stackoverflow.com/a/14162161/2138322
func interfacePointer(data interface{}) reflect.Value {
var ptr reflect.Value
value := reflect.ValueOf(data)
if value.Type().Kind() == reflect.Ptr {
ptr = value
value = ptr.Elem() // acquire value referenced by pointer
} else {
ptr = reflect.New(reflect.TypeOf(data)) // create new pointer
temp := ptr.Elem() // create variable to value of pointer
temp.Set(value) // set value of variable to our passed in value
}
return ptr
}
func setInterfaceValue(baseStruct reflect.Value, fromStruct reflect.Value) {
baseStruct.Set(fromStruct)
}
func hasKey(key string, object interface{}) int {
fields := getFieldsName(object)
for index, fieldName := range fields {
if fieldName == key {
return index
}
}
return -1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment