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} }