Aug 24, 2019

[Go] Awkward use of reflection

I would say the usage is a bit awkward, rule of thumb, unless necessary, reflect takes lot's of runtime speed.
Don't Do It.

package main

import (
 "fmt"
 "reflect"
)

type A struct{ Name string }
type B struct{ Age int }
type C struct{ Address string }

func Merge(a interface{}, b interface{})( d interface{}) {
 aType := reflect.TypeOf(a)
 if aType.Kind() != reflect.Struct {
  panic("a is not a struct")
 }

 bType := reflect.TypeOf(b)
 if bType.Kind() != reflect.Struct {
  panic("b is not a struct")
 }

 var fields []reflect.StructField
 for i:=0 ; i< aType.NumField(); i++{
   fields =append(fields, aType.Field(i))
 }
 for i:=0 ; i< bType.NumField(); i++{
   fields =append(fields, bType.Field(i))
 }

 dType := reflect.StructOf(fields)
 dVal := reflect.Indirect(reflect.New(dType))


 aVal := reflect.ValueOf(a)
 bVal := reflect.ValueOf(b)
 

 for i := 0; i < aType.NumField(); i++ {
  dVal.FieldByName(aType.Field(i).Name).Set(aVal.Field(i))
 }
 for i := 0; i < bType.NumField(); i++ {
  dVal.FieldByName(bType.Field(i).Name).Set(bVal.Field(i))
 }
 
 d = dVal.Interface()
  
 return 
}

func main() {
 a, b, c := A{"John"}, B{42}, C{"World"}

 d1 := Merge(a, b)
 d2 := Merge(a, c)
 d3 := Merge(b, c)

 fmt.Printf("%#v\n",d1)
 fmt.Printf("%#v\n",d2)
 fmt.Printf("%#v\n",d3)
}

Output:
struct { Name string; Age int }{Name:"John", Age:42}
struct { Name string; Address string }{Name:"John", Address:"World"}
struct { Age int; Address string }{Age:42, Address:"World"}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.