I have a situation where I have two data structures. Each is statically typed as an interface{} and can either be an int, string, slice, or map. The function should be able to merge these two data structures together, except in some cases (for instance, you can t merge a string with a map). I ve written the following code which works, but I m wondering if there is a more elegant approach.
package main
import (
"fmt"
"reflect"
)
func mergeDataStructures(a, b interface{}) (interface{}, error) {
var retVal interface{}
switch a.(type) {
case string, int:
switch b.(type) {
case string, int:
retVal = []interface{}{}
retVal = append(retVal.([]interface{}), b)
retVal = append(retVal.([]interface{}), a)
case []interface{}:
retVal = append(retVal.([]interface{}), a)
case map[interface{}]interface{}:
return nil, fmt.Errorf("unable to merge string with map")
default:
return nil, fmt.Errorf("unknown value type %q", reflect.TypeOf(b))
}
case []interface{}:
switch b.(type) {
case string, int:
retVal = []interface{}{}
retVal = append(retVal.([]interface{}), a.([]interface{})...)
retVal = append(retVal.([]interface{}), b)
case []interface{}:
retVal = []interface{}{}
retVal = append(retVal.([]interface{}), a.([]interface{})...)
retVal = append(retVal.([]interface{}), b.([]interface{})...)
case map[interface{}]interface{}:
return nil, fmt.Errorf("unable to merge slice with map")
default:
return nil, fmt.Errorf("unknown value type %q", reflect.TypeOf(b))
}
case map[interface{}]interface{}:
switch b.(type) {
case string, int:
return nil, fmt.Errorf("unable to merge map with string")
case []interface{}:
return nil, fmt.Errorf("unable to merge map with slice")
case map[interface{}]interface{}:
retVal = make(map[interface{}]interface{})
for k, v := range a.(map[interface{}]interface{}) {
retVal.(map[interface{}]interface{})[k] = v
}
for k, v := range b.(map[interface{}]interface{}) {
retVal.(map[interface{}]interface{})[k] = v
}
default:
return nil, fmt.Errorf("unknown value type %q", reflect.TypeOf(b))
}
default:
return nil, fmt.Errorf("unknown value type %q", reflect.TypeOf(a))
}
return retVal, nil
}
func main() {
var a, b interface{}
a = []interface{}{1,2,3}
b = 4
c, err := mergeDataStructures(a, b)
if err != nil {
panic(err)
}
fmt.Printf("%#v
", c) // prints: []interface{}{1,2,3,4}
}