How to convert interface{} to map

后端 未结 3 515
慢半拍i
慢半拍i 2021-01-31 08:43

I am trying to create a function that could accept following

*struct
[]*struct
map[string]*struct

Here struct could be any struct not just a sp

相关标签:
3条回答
  • 2021-01-31 09:16

    If the map value can be any type, then use reflect to iterate through the map:

    if v.Kind() == reflect.Map {
        for _, key := range v.MapKeys() {
            strct := v.MapIndex(key)
            fmt.Println(key.Interface(), strct.Interface())
        }
    }
    

    playground example

    If there's a small and known set of struct types, then a type switch can be used:

    func process(in interface{}) {
      switch v := in.(type) {
      case map[string]*Book:
         for s, b := range v {
             // b has type *Book
             fmt.Printf("%s: book=%v\n" s, b)
         }
      case map[string]*Author:
         for s, a := range v {
             // a has type *Author
             fmt.Printf("%s: author=%v\n" s, a)
         }
       case []*Book:
         for i, b := range v {
             fmt.Printf("%d: book=%v\n" i, b)
         }
       case []*Author:
         for i, a := range v {
             fmt.Printf("%d: author=%v\n" i, a)
         }
       case *Book:
         fmt.Ptintf("book=%v\n", v)
       case *Author:
         fmt.Printf("author=%v\n", v)
       default:
         // handle unknown type
       }
    }
    
    0 讨论(0)
  • 2021-01-31 09:16

    Another way to convert an interface{} into a map with the package reflect is with MapRange.

    I quote:

    MapRange returns a range iterator for a map. It panics if v's Kind is not Map.

    Call Next to advance the iterator, and Key/Value to access each entry. Next returns false when the iterator is exhausted. MapRange follows the same iteration semantics as a range statement.

    Example:

    iter := reflect.ValueOf(m).MapRange()
    for iter.Next() {
        key := iter.Key().Interface()
        value := iter.Value().Interface()
        ...
    }
    
    0 讨论(0)
  • 2021-01-31 09:25

    You don't need reflect here. Try:

    v, ok := in.(map[string]*Book)
    if !ok {
        // Can't assert, handle error.
    }
    for _, s := range v {
        fmt.Printf("Value: %v\n", s)
    }
    

    Same goes for the rest of your function. It looks like you're using reflection when you would be better served by a type switch.


    Alternatively, if you insist on using reflection here (which doesn't make a lot of sense) you can also use Value.MapKeys with the result from your ValueOf (see the answer https://stackoverflow.com/a/38186057/714501)

    0 讨论(0)
提交回复
热议问题