How can I merge arbitrary data structures in Go

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

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

Answers

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/40679748/how-can-i-merge-arbitrary-data-structures-in-go

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils