I want to create a function called merge()
that takes in two values of the same struct, but of any struct, and returns the merged values of the two structs.
I want the first value to take precedence. For example, if there are two structs a
and b
, after calling merge(a,b)
, if there are fields that both a
and b
contain, I want it to have a
's value for that given field.
What would be the best way to implement this? https://play.golang.org/p/7s9PWx26gfz
type cat struct {
name string
color string
age int
}
type book struct {
title string
author string
}
func main() {
c1 := cat{
name: "Oscar",
color: "",
age: 3,
}
c2 := cat{
name: "",
color: "orange",
age: 2,
}
c3 := merge(c1, c2)
// want: c3 = cat{
// name: "Oscar",
// color: "orange",
// age: 3,
// }
// another case...
b1 := book{
title: "Lord of the Rings",
author: "John Smith",
}
b2 := book{
title: "Harry Potter",
author: "",
}
b3 := merge(b1, b2)
// want: b3 = book{
// title: "Lord of the Rings",
// author: "John Smith",
// }
}
This is what I have so far:
// merges two structs, where a's values take precendence over b's values (a's values will be kept over b's if each field has a value)
func merge(a, b interface{}) (*interface{}, error) {
var result interface{}
aFields := reflect.Fields(a)
bFields := reflect.Fields(b)
if !reflect.DeepEqual(aFields, bFields) {
return &result, errors.New("cannot merge structs of different struct types")
}
aValOf := reflect.ValueOf(a)
bValOf := reflect.ValueOf(b)
resultValOf := reflect.ValueOf(result)
aValues := make([]interface{}, aValOf.NumField())
resultValues := make([]interface{}, resultValOf.NumField())
for i := 0; i < aValOf.NumField(); i++ {
if reflect.ValueOf(aValues[i]).IsNil() {
resultValues[i] = bValOf.Field(i).Interface()
break
}
resultValues[i] = aValOf.Field(i).Interface()
}
return &result, nil
}