title: How can I merge arbitrary data structures in Go?
body: <p>I have a situation where I have two data structures.  Each is statically typed as an <code>interface{}</code> 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.</p>
  
  <pre><code>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\n", c) // prints: []interface{}{1,2,3,4}
  }
  </code></pre>